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 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
44 struct proc_dir_entry *temp;
50 while (temp != NULL) {
51 if (strcmp(temp->name, name) == 0)
59 /* lprocfs API calls */
61 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
64 if (root == NULL || list == NULL)
67 while (list->name != NULL) {
68 struct proc_dir_entry *cur_root, *proc;
69 char *pathcopy, *cur, *next, pathbuf[64];
70 int pathsize = strlen(list->name) + 1;
75 /* need copy of path for strsep */
76 if (strlen(list->name) > sizeof(pathbuf) - 1) {
77 OBD_ALLOC(pathcopy, pathsize);
85 strcpy(pathcopy, list->name);
87 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
88 if (*cur =='\0') /* skip double/trailing "/" */
91 proc = lprocfs_srch(cur_root, cur);
92 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
93 cur_root->name, cur, next,
94 (proc ? "exists" : "new"));
96 cur_root = (proc ? proc :
97 proc_mkdir(cur, cur_root));
98 } else if (proc == NULL) {
102 if (list->write_fptr)
104 proc = create_proc_entry(cur, mode, cur_root);
108 if (pathcopy != pathbuf)
109 OBD_FREE(pathcopy, pathsize);
111 if (cur_root == NULL || proc == NULL) {
112 CERROR("LprocFS: No memory to create /proc entry %s",
117 proc->read_proc = list->read_fptr;
118 proc->write_proc = list->write_fptr;
119 proc->data = (list->data ? list->data : data);
125 void lprocfs_remove(struct proc_dir_entry *root)
127 struct proc_dir_entry *temp = root;
128 struct proc_dir_entry *rm_entry;
129 struct proc_dir_entry *parent;
131 LASSERT(root != NULL);
132 parent = root->parent;
133 LASSERT(parent != NULL);
136 while (temp->subdir != NULL)
142 /* Memory corruption once caused this to fail, and
143 without this LASSERT we would loop here forever. */
144 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
145 "0x%p %s/%s len %d\n", rm_entry, temp->name,
146 rm_entry->name, (int)strlen(rm_entry->name));
148 remove_proc_entry(rm_entry->name, rm_entry->parent);
154 struct proc_dir_entry *lprocfs_register(const char *name,
155 struct proc_dir_entry *parent,
156 struct lprocfs_vars *list, void *data)
158 struct proc_dir_entry *newchild;
160 newchild = lprocfs_srch(parent, name);
161 if (newchild != NULL) {
162 CERROR(" Lproc: Attempting to register %s more than once \n",
164 return ERR_PTR(-EALREADY);
167 newchild = proc_mkdir(name, parent);
168 if (newchild != NULL && list != NULL) {
169 int rc = lprocfs_add_vars(newchild, list, data);
171 lprocfs_remove(newchild);
178 /* Generic callbacks */
180 int lprocfs_rd_u64(char *page, char **start, off_t off,
181 int count, int *eof, void *data)
183 LASSERT(data != NULL);
185 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
188 int lprocfs_rd_atomic(char *page, char **start, off_t off,
189 int count, int *eof, void *data)
191 atomic_t *atom = (atomic_t *)data;
192 LASSERT(atom != NULL);
194 return snprintf(page, count, "%d\n", atomic_read(atom));
197 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
198 int *eof, void *data)
200 struct obd_device *obd = (struct obd_device*)data;
202 LASSERT(obd != NULL);
204 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
207 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
208 int *eof, void* data)
210 struct obd_device *dev = (struct obd_device *)data;
212 LASSERT(dev != NULL);
213 LASSERT(dev->obd_name != NULL);
215 return snprintf(page, count, "%s\n", dev->obd_name);
218 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
221 struct obd_device *obd = (struct obd_device *)data;
223 LASSERT(obd != NULL);
224 LASSERT(obd->obd_fsops != NULL);
225 LASSERT(obd->obd_fsops->fs_type != NULL);
226 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
229 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
230 int *eof, void *data)
232 struct obd_statfs osfs;
233 int rc = obd_statfs(data, &osfs, jiffies - HZ);
236 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
241 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
242 int *eof, void *data)
244 struct obd_statfs osfs;
245 int rc = obd_statfs(data, &osfs, jiffies - HZ);
247 __u32 blk_size = osfs.os_bsize >> 10;
248 __u64 result = osfs.os_blocks;
250 while (blk_size >>= 1)
254 rc = snprintf(page, count, LPU64"\n", result);
259 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
260 int *eof, void *data)
262 struct obd_statfs osfs;
263 int rc = obd_statfs(data, &osfs, jiffies - HZ);
265 __u32 blk_size = osfs.os_bsize >> 10;
266 __u64 result = osfs.os_bfree;
268 while (blk_size >>= 1)
272 rc = snprintf(page, count, LPU64"\n", result);
277 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
278 int *eof, void *data)
280 struct obd_statfs osfs;
281 int rc = obd_statfs(data, &osfs, jiffies - HZ);
283 __u32 blk_size = osfs.os_bsize >> 10;
284 __u64 result = osfs.os_bavail;
286 while (blk_size >>= 1)
290 rc = snprintf(page, count, LPU64"\n", result);
295 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
296 int *eof, void *data)
298 struct obd_statfs osfs;
299 int rc = obd_statfs(data, &osfs, jiffies - HZ);
302 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
308 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
309 int *eof, void *data)
311 struct obd_statfs osfs;
312 int rc = obd_statfs(data, &osfs, jiffies - HZ);
315 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
320 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
321 int *eof, void *data)
323 struct obd_device *obd = (struct obd_device *)data;
324 struct obd_import *imp;
325 char *imp_state_name = NULL;
327 LASSERT(obd != NULL);
328 imp = obd->u.cli.cl_import;
329 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
331 return snprintf(page, count, "%s\t%s%s\n",
332 obd2cli_tgt(obd), imp_state_name,
333 imp->imp_deactive ? "\tDEACTIVATED" : "");
336 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
337 int *eof, void *data)
339 struct obd_device *obd = (struct obd_device*)data;
340 struct ptlrpc_connection *conn;
342 LASSERT(obd != NULL);
343 conn = obd->u.cli.cl_import->imp_connection;
344 LASSERT(conn != NULL);
346 return snprintf(page, count, "%s\n", conn->c_remote_uuid.uuid);
349 static const char *obd_connect_names[] = {
369 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
370 int count, int *eof, void *data)
372 struct obd_device *obd = data;
373 __u64 mask = 1, flags;
379 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
380 ret = snprintf(page, count, "flags="LPX64"\n", flags);
381 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
383 ret += snprintf(page + ret, count - ret, "%s\n",
384 obd_connect_names[i]);
386 if (flags & ~(mask - 1))
387 ret += snprintf(page + ret, count - ret,
388 "unknown flags "LPX64"\n", flags & ~(mask - 1));
392 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
394 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
395 int *eof, void *data)
397 struct obd_device *obd = (struct obd_device*)data;
399 LASSERT(obd != NULL);
401 return snprintf(page, count, "%u\n", obd->obd_num_exports);
404 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
405 int *eof, void *data)
407 struct obd_type *class = (struct obd_type*) data;
409 LASSERT(class != NULL);
411 return snprintf(page, count, "%d\n", class->typ_refcnt);
414 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
418 LASSERT(obd != NULL);
419 LASSERT(obd->obd_type != NULL);
420 LASSERT(obd->obd_type->typ_procroot != NULL);
422 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
423 obd->obd_type->typ_procroot,
425 if (IS_ERR(obd->obd_proc_entry)) {
426 rc = PTR_ERR(obd->obd_proc_entry);
427 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
428 obd->obd_proc_entry = NULL;
433 int lprocfs_obd_cleanup(struct obd_device *obd)
435 if (obd && obd->obd_proc_entry) {
436 lprocfs_remove(obd->obd_proc_entry);
437 obd->obd_proc_entry = NULL;
442 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num)
444 struct lprocfs_stats *stats;
445 struct lprocfs_percpu *percpu;
446 unsigned int percpusize;
452 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_online_cpus()]));
456 percpusize = L1_CACHE_ALIGN(offsetof(typeof(*percpu), lp_cntr[num]));
457 stats->ls_percpu_size = num_online_cpus() * percpusize;
458 OBD_ALLOC(stats->ls_percpu[0], stats->ls_percpu_size);
459 if (stats->ls_percpu[0] == NULL) {
460 OBD_FREE(stats, offsetof(typeof(*stats),
461 ls_percpu[num_online_cpus()]));
466 for (i = 1; i < num_online_cpus(); i++)
467 stats->ls_percpu[i] = (void *)(stats->ls_percpu[i - 1]) +
473 void lprocfs_free_stats(struct lprocfs_stats *stats)
475 if (stats->ls_num == 0)
478 OBD_FREE(stats->ls_percpu[0], stats->ls_percpu_size);
479 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_online_cpus()]));
482 /* Reset counter under lock */
483 int lprocfs_counter_write(struct file *file, const char *buffer,
484 unsigned long count, void *data)
490 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
492 struct lprocfs_stats *stats = p->private;
493 /* return 1st cpu location */
494 return (*pos >= stats->ls_num) ? NULL :
495 &(stats->ls_percpu[0]->lp_cntr[*pos]);
498 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
502 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
504 struct lprocfs_stats *stats = p->private;
506 return (*pos >= stats->ls_num) ? NULL :
507 &(stats->ls_percpu[0]->lp_cntr[*pos]);
510 /* seq file export of one lprocfs counter */
511 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
513 struct lprocfs_stats *stats = p->private;
514 struct lprocfs_counter *cntr = v;
515 struct lprocfs_counter t, ret = { .lc_min = ~(__u64)0 };
518 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
520 do_gettimeofday(&now);
521 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
522 "snapshot_time", now.tv_sec, now.tv_usec);
526 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
528 for (i = 0; i < num_online_cpus(); i++) {
529 struct lprocfs_counter *percpu_cntr =
530 &(stats->ls_percpu[i])->lp_cntr[idx];
534 centry = atomic_read(&percpu_cntr->lc_cntl.la_entry);
535 t.lc_count = percpu_cntr->lc_count;
536 t.lc_sum = percpu_cntr->lc_sum;
537 t.lc_min = percpu_cntr->lc_min;
538 t.lc_max = percpu_cntr->lc_max;
539 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
540 } while (centry != atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
541 centry != atomic_read(&percpu_cntr->lc_cntl.la_exit));
542 ret.lc_count += t.lc_count;
543 ret.lc_sum += t.lc_sum;
544 if (t.lc_min < ret.lc_min)
545 ret.lc_min = t.lc_min;
546 if (t.lc_max > ret.lc_max)
547 ret.lc_max = t.lc_max;
548 ret.lc_sumsquare += t.lc_sumsquare;
551 rc = seq_printf(p, "%-25s "LPU64" samples [%s]", cntr->lc_name,
552 ret.lc_count, cntr->lc_units);
556 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
557 rc = seq_printf(p, " "LPU64" "LPU64" "LPU64,
558 ret.lc_min, ret.lc_max, ret.lc_sum);
561 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
562 rc = seq_printf(p, " "LPU64, ret.lc_sumsquare);
566 rc = seq_printf(p, "\n");
568 return (rc < 0) ? rc : 0;
571 struct seq_operations lprocfs_stats_seq_sops = {
572 start: lprocfs_stats_seq_start,
573 stop: lprocfs_stats_seq_stop,
574 next: lprocfs_stats_seq_next,
575 show: lprocfs_stats_seq_show,
578 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
580 struct proc_dir_entry *dp = PDE(inode);
581 struct seq_file *seq;
584 rc = seq_open(file, &lprocfs_stats_seq_sops);
587 seq = file->private_data;
588 seq->private = dp->data;
592 struct file_operations lprocfs_stats_seq_fops = {
593 .owner = THIS_MODULE,
594 .open = lprocfs_stats_seq_open,
597 .release = seq_release,
600 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
601 struct lprocfs_stats *stats)
603 struct proc_dir_entry *entry;
604 LASSERT(root != NULL);
606 entry = create_proc_entry(name, 0444, root);
609 entry->proc_fops = &lprocfs_stats_seq_fops;
610 entry->data = (void *)stats;
611 entry->write_proc = lprocfs_counter_write;
615 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
616 unsigned conf, const char *name, const char *units)
618 struct lprocfs_counter *c;
621 LASSERT(stats != NULL);
622 for (i = 0; i < num_online_cpus(); i++) {
623 c = &(stats->ls_percpu[i]->lp_cntr[index]);
625 c->lc_min = ~(__u64)0;
630 EXPORT_SYMBOL(lprocfs_counter_init);
632 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
634 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
635 LASSERT(coffset < stats->ls_num); \
636 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
639 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
641 struct lprocfs_stats *stats;
642 unsigned int num_stats;
645 LASSERT(obd->obd_stats == NULL);
646 LASSERT(obd->obd_proc_entry != NULL);
647 LASSERT(obd->obd_cntr_base == 0);
649 num_stats = 1 + OBD_COUNTER_OFFSET(quotactl) +
651 stats = lprocfs_alloc_stats(num_stats);
655 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
656 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
657 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
658 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
659 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
660 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
661 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
662 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
663 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
664 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
665 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
666 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
667 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
668 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
669 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
670 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
671 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
672 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
673 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
674 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
675 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
676 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
677 LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd);
678 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
679 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
680 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
681 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
682 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
683 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
684 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
685 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
686 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw_async);
687 LPROCFS_OBD_OP_INIT(num_private_stats, stats, prep_async_page);
688 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_async_io);
689 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_group_io);
690 LPROCFS_OBD_OP_INIT(num_private_stats, stats, trigger_group_io);
691 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_async_flags);
692 LPROCFS_OBD_OP_INIT(num_private_stats, stats, teardown_async_page);
693 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
694 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
695 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
696 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
697 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
698 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
699 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
700 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
701 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
702 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
703 LPROCFS_OBD_OP_INIT(num_private_stats, stats, match);
704 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
705 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
706 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
707 LPROCFS_OBD_OP_INIT(num_private_stats, stats, join_lru);
708 LPROCFS_OBD_OP_INIT(num_private_stats, stats, san_preprw);
709 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
710 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
711 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
712 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
713 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
714 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
715 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
716 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
717 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
718 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
719 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
721 for (i = num_private_stats; i < num_stats; i++) {
722 /* If this LBUGs, it is likely that an obd
723 * operation was added to struct obd_ops in
724 * <obd.h>, and that the corresponding line item
725 * LPROCFS_OBD_OP_INIT(.., .., opname)
726 * is missing from the list above. */
727 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
728 CERROR("Missing obd_stat initializer obd_op "
729 "operation at offset %d. Aborting.\n",
730 i - num_private_stats);
734 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
736 lprocfs_free_stats(stats);
738 obd->obd_stats = stats;
739 obd->obd_cntr_base = num_private_stats;
744 void lprocfs_free_obd_stats(struct obd_device *obd)
746 struct lprocfs_stats *stats = obd->obd_stats;
749 obd->obd_stats = NULL;
750 lprocfs_free_stats(stats);
754 #define LPROCFS_MD_OP_INIT(base, stats, op) \
756 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
757 LASSERT(coffset < stats->ls_num); \
758 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
761 int lprocfs_alloc_md_stats(struct obd_device *obd,
762 unsigned num_private_stats)
764 struct lprocfs_stats *stats;
765 unsigned int num_stats;
768 LASSERT(obd->md_stats == NULL);
769 LASSERT(obd->obd_proc_entry != NULL);
770 LASSERT(obd->md_cntr_base == 0);
772 num_stats = 1 + MD_COUNTER_OFFSET(cancel_unused) +
774 stats = lprocfs_alloc_stats(num_stats);
778 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
779 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
780 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
781 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
782 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
783 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
784 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
785 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
786 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
787 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
788 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
789 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
790 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
791 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
792 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
793 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
794 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
795 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
796 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
797 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
798 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
799 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
800 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
801 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
802 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
804 for (i = num_private_stats; i < num_stats; i++) {
805 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
806 CERROR("Missing md_stat initializer md_op "
807 "operation at offset %d. Aborting.\n",
808 i - num_private_stats);
812 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
814 lprocfs_free_stats(stats);
816 obd->md_stats = stats;
817 obd->md_cntr_base = num_private_stats;
822 void lprocfs_free_md_stats(struct obd_device *obd)
824 struct lprocfs_stats *stats = obd->md_stats;
827 obd->md_stats = NULL;
828 lprocfs_free_stats(stats);
832 int lprocfs_write_helper(const char *buffer, unsigned long count,
835 char kernbuf[20], *end;
837 if (count > (sizeof(kernbuf) - 1))
840 if (copy_from_user(kernbuf, buffer, count))
843 kernbuf[count] = '\0';
845 *val = simple_strtol(kernbuf, &end, 0);
852 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
854 char kernbuf[22], *end;
856 if (count > (sizeof(kernbuf) - 1))
859 if (copy_from_user(kernbuf, buffer, count))
862 kernbuf[count] = '\0';
864 if (kernbuf[0] == '-')
865 *val = -simple_strtoull(kernbuf + 1, &end, 0);
867 *val = simple_strtoull(kernbuf, &end, 0);
874 int lprocfs_obd_seq_create(struct obd_device *dev, char *name, mode_t mode,
875 struct file_operations *seq_fops, void *data)
877 struct proc_dir_entry *entry;
880 entry = create_proc_entry(name, mode, dev->obd_proc_entry);
883 entry->proc_fops = seq_fops;
888 EXPORT_SYMBOL(lprocfs_obd_seq_create);
890 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
894 if (value >= OBD_HIST_MAX)
895 value = OBD_HIST_MAX - 1;
897 spin_lock_irqsave(&oh->oh_lock, flags);
898 oh->oh_buckets[value]++;
899 spin_unlock_irqrestore(&oh->oh_lock, flags);
901 EXPORT_SYMBOL(lprocfs_oh_tally);
903 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
907 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
910 lprocfs_oh_tally(oh, val);
912 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
914 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
916 unsigned long ret = 0;
919 for (i = 0; i < OBD_HIST_MAX; i++)
920 ret += oh->oh_buckets[i];
923 EXPORT_SYMBOL(lprocfs_oh_sum);
925 void lprocfs_oh_clear(struct obd_histogram *oh)
928 spin_lock_irqsave(&oh->oh_lock, flags);
929 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
930 spin_unlock_irqrestore(&oh->oh_lock, flags);
932 EXPORT_SYMBOL(lprocfs_oh_clear);
934 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
935 int count, int *eof, void *data)
937 struct obd_device *obd = data;
939 connected = obd->obd_connected_clients,
940 max_recoverable = obd->obd_max_recoverable_clients,
941 recoverable = obd->obd_recoverable_clients,
942 completed = max_recoverable - recoverable,
943 queue_len = obd->obd_requests_queued_for_recovery,
944 replayed = obd->obd_replayed_requests;
945 __u64 next_transno = obd->obd_next_recovery_transno;
947 LASSERT(obd != NULL);
950 n = snprintf(page, count, "status: ");
951 page += n; len += n; count -= n;
952 if (obd->obd_max_recoverable_clients == 0) {
953 n = snprintf(page, count, "INACTIVE\n");
957 /* sampled unlocked, but really... */
958 if (obd->obd_recovering == 0) {
959 n = snprintf(page, count, "COMPLETE\n");
960 page += n; len += n; count -= n;
962 n = snprintf(page, count, "recovery_start: %lu\n",
963 obd->obd_recovery_start);
964 page += n; len += n; count -= n;
965 n = snprintf(page, count, "recovery_end: %lu\n",
966 obd->obd_recovery_end);
967 page += n; len += n; count -= n;
968 n = snprintf(page, count, "recovered_clients: %d\n",
970 page += n; len += n; count -= n;
971 n = snprintf(page, count, "unrecovered_clients: %d\n",
972 obd->obd_recoverable_clients);
973 page += n; len += n; count -= n;
974 n = snprintf(page, count, "last_transno: "LPD64"\n",
976 page += n; len += n; count -= n;
977 n = snprintf(page, count, "replayed_requests: %d\n", replayed);
981 n = snprintf(page, count, "RECOVERING\n");
982 page += n; len += n; count -= n;
983 n = snprintf(page, count, "recovery_start: %lu\n",
984 obd->obd_recovery_start);
985 page += n; len += n; count -= n;
986 n = snprintf(page, count, "time remaining: %lu\n",
987 CURRENT_SECONDS >= obd->obd_recovery_end ? 0 :
988 obd->obd_recovery_end - CURRENT_SECONDS);
989 page += n; len += n; count -= n;
990 n = snprintf(page, count, "connected_clients: %d/%d\n",
991 connected, max_recoverable);
992 page += n; len += n; count -= n;
993 n = snprintf(page, count, "completed_clients: %d/%d\n",
994 completed, max_recoverable);
995 page += n; len += n; count -= n;
996 n = snprintf(page, count, "replayed_requests: %d/??\n", replayed);
997 page += n; len += n; count -= n;
998 n = snprintf(page, count, "queued_requests: %d\n", queue_len);
999 page += n; len += n; count -= n;
1000 n = snprintf(page, count, "next_transno: "LPD64"\n", next_transno);
1003 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
1005 EXPORT_SYMBOL(lprocfs_register);
1006 EXPORT_SYMBOL(lprocfs_srch);
1007 EXPORT_SYMBOL(lprocfs_remove);
1008 EXPORT_SYMBOL(lprocfs_add_vars);
1009 EXPORT_SYMBOL(lprocfs_obd_setup);
1010 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1011 EXPORT_SYMBOL(lprocfs_alloc_stats);
1012 EXPORT_SYMBOL(lprocfs_free_stats);
1013 EXPORT_SYMBOL(lprocfs_register_stats);
1014 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1015 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1017 EXPORT_SYMBOL(lprocfs_rd_u64);
1018 EXPORT_SYMBOL(lprocfs_rd_atomic);
1019 EXPORT_SYMBOL(lprocfs_rd_uuid);
1020 EXPORT_SYMBOL(lprocfs_rd_name);
1021 EXPORT_SYMBOL(lprocfs_rd_fstype);
1022 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
1023 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
1024 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1025 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1027 EXPORT_SYMBOL(lprocfs_rd_blksize);
1028 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
1029 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
1030 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
1031 EXPORT_SYMBOL(lprocfs_rd_filestotal);
1032 EXPORT_SYMBOL(lprocfs_rd_filesfree);
1034 EXPORT_SYMBOL(lprocfs_write_helper);
1035 EXPORT_SYMBOL(lprocfs_write_u64_helper);