1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/obdclass/lprocfs_status.c
38 * Author: Hariharan Thantry <thantry@users.sourceforge.net>
42 # define EXPORT_SYMTAB
44 #define DEBUG_SUBSYSTEM S_CLASS
47 # include <liblustre.h>
50 #include <obd_class.h>
51 #include <lprocfs_status.h>
52 #include <lustre_fsfilt.h>
53 #include <lustre_log.h>
54 #include <lustre/lustre_idl.h>
58 #define MAX_STRING_SIZE 128
60 /* for bug 10866, global variable */
61 DECLARE_RWSEM(_lprocfs_lock);
62 EXPORT_SYMBOL(_lprocfs_lock);
64 int lprocfs_seq_release(struct inode *inode, struct file *file)
67 return seq_release(inode, file);
69 EXPORT_SYMBOL(lprocfs_seq_release);
71 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
74 struct proc_dir_entry *temp;
81 while (temp != NULL) {
82 if (strcmp(temp->name, name) == 0) {
93 /* lprocfs API calls */
95 /* Function that emulates snprintf but also has the side effect of advancing
96 the page pointer for the next write into the buffer, incrementing the total
97 length written to the buffer, and decrementing the size left in the
99 static int lprocfs_obd_snprintf(char **page, int end, int *len,
100 const char *format, ...)
108 va_start(list, format);
109 n = vsnprintf(*page, end - *len, format, list);
112 *page += n; *len += n;
116 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
118 read_proc_t *read_proc,
119 write_proc_t *write_proc,
121 struct file_operations *fops)
123 cfs_proc_dir_entry_t *proc;
126 if (root == NULL || name == NULL)
127 return ERR_PTR(-EINVAL);
134 proc = create_proc_entry(name, mode, root);
136 CERROR("LprocFS: No memory to create /proc entry %s", name);
137 return ERR_PTR(-ENOMEM);
139 proc->read_proc = read_proc;
140 proc->write_proc = write_proc;
143 proc->proc_fops = fops;
147 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
148 struct proc_dir_entry *parent, const char *dest)
150 struct proc_dir_entry *entry;
152 if (parent == NULL || dest == NULL)
155 entry = proc_symlink(name, parent, dest);
157 CERROR("LprocFS: Could not create symbolic link from %s to %s",
162 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
163 size_t size, loff_t *ppos)
165 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
166 char *page, *start = NULL;
167 int rc = 0, eof = 1, count;
169 if (*ppos >= CFS_PAGE_SIZE)
172 page = (char *)__get_free_page(GFP_KERNEL);
177 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
178 if (!dp->deleted && dp->read_proc)
179 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
185 /* for lustre proc read, the read count must be less than PAGE_SIZE */
194 start = page + *ppos;
195 } else if (start < page) {
199 count = (rc < size) ? rc : size;
200 if (copy_to_user(buf, start, count)) {
207 free_page((unsigned long)page);
211 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
212 size_t size, loff_t *ppos)
214 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
218 if (!dp->deleted && dp->write_proc)
219 rc = dp->write_proc(f, buf, size, dp->data);
224 static struct file_operations lprocfs_generic_fops = {
225 .owner = THIS_MODULE,
226 .read = lprocfs_fops_read,
227 .write = lprocfs_fops_write,
230 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
232 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
233 struct obd_device *obd = dp->data;
235 atomic_inc(&obd->obd_evict_inprogress);
240 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
242 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
243 struct obd_device *obd = dp->data;
245 atomic_dec(&obd->obd_evict_inprogress);
246 wake_up(&obd->obd_evict_inprogress_waitq);
251 struct file_operations lprocfs_evict_client_fops = {
252 .owner = THIS_MODULE,
253 .read = lprocfs_fops_read,
254 .write = lprocfs_fops_write,
255 .open = lprocfs_evict_client_open,
256 .release = lprocfs_evict_client_release,
258 EXPORT_SYMBOL(lprocfs_evict_client_fops);
263 * \param root [in] The parent proc entry on which new entry will be added.
264 * \param list [in] Array of proc entries to be added.
265 * \param data [in] The argument to be passed when entries read/write routines
266 * are called through /proc file.
268 * \retval 0 on success
271 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
274 if (root == NULL || list == NULL)
277 while (list->name != NULL) {
278 struct proc_dir_entry *cur_root, *proc;
279 char *pathcopy, *cur, *next, pathbuf[64];
280 int pathsize = strlen(list->name) + 1;
285 /* need copy of path for strsep */
286 if (strlen(list->name) > sizeof(pathbuf) - 1) {
287 OBD_ALLOC(pathcopy, pathsize);
288 if (pathcopy == NULL)
295 strcpy(pathcopy, list->name);
297 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
298 if (*cur =='\0') /* skip double/trailing "/" */
301 proc = lprocfs_srch(cur_root, cur);
302 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
303 cur_root->name, cur, next,
304 (proc ? "exists" : "new"));
306 cur_root = (proc ? proc :
307 proc_mkdir(cur, cur_root));
308 } else if (proc == NULL) {
310 if (list->proc_mode != 0000) {
311 mode = list->proc_mode;
315 if (list->write_fptr)
318 proc = create_proc_entry(cur, mode, cur_root);
322 if (pathcopy != pathbuf)
323 OBD_FREE(pathcopy, pathsize);
325 if (cur_root == NULL || proc == NULL) {
326 CERROR("LprocFS: No memory to create /proc entry %s",
332 proc->proc_fops = list->fops;
334 proc->proc_fops = &lprocfs_generic_fops;
335 proc->read_proc = list->read_fptr;
336 proc->write_proc = list->write_fptr;
337 proc->data = (list->data ? list->data : data);
343 void lprocfs_remove(struct proc_dir_entry **rooth)
345 struct proc_dir_entry *root = *rooth;
346 struct proc_dir_entry *temp = root;
347 struct proc_dir_entry *rm_entry;
348 struct proc_dir_entry *parent;
354 parent = root->parent;
355 LASSERT(parent != NULL);
356 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
359 while (temp->subdir != NULL)
365 /* Memory corruption once caused this to fail, and
366 without this LASSERT we would loop here forever. */
367 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
368 "0x%p %s/%s len %d\n", rm_entry, temp->name,
369 rm_entry->name, (int)strlen(rm_entry->name));
371 /* Now, the rm_entry->deleted flags is protected
372 * by _lprocfs_lock. */
373 rm_entry->data = NULL;
374 remove_proc_entry(rm_entry->name, temp);
378 LPROCFS_WRITE_EXIT();
381 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
383 LASSERT(parent != NULL);
384 remove_proc_entry(name, parent);
387 struct proc_dir_entry *lprocfs_register(const char *name,
388 struct proc_dir_entry *parent,
389 struct lprocfs_vars *list, void *data)
391 struct proc_dir_entry *newchild;
393 newchild = lprocfs_srch(parent, name);
394 if (newchild != NULL) {
395 CERROR(" Lproc: Attempting to register %s more than once \n",
397 return ERR_PTR(-EALREADY);
400 newchild = proc_mkdir(name, parent);
401 if (newchild != NULL && list != NULL) {
402 int rc = lprocfs_add_vars(newchild, list, data);
404 lprocfs_remove(&newchild);
411 /* Generic callbacks */
412 int lprocfs_rd_uint(char *page, char **start, off_t off,
413 int count, int *eof, void *data)
415 unsigned int *temp = data;
416 return snprintf(page, count, "%u\n", *temp);
419 int lprocfs_wr_uint(struct file *file, const char *buffer,
420 unsigned long count, void *data)
423 char dummy[MAX_STRING_SIZE + 1], *end;
426 dummy[MAX_STRING_SIZE] = '\0';
427 if (copy_from_user(dummy, buffer, MAX_STRING_SIZE))
430 tmp = simple_strtoul(dummy, &end, 0);
434 *p = (unsigned int)tmp;
438 int lprocfs_rd_u64(char *page, char **start, off_t off,
439 int count, int *eof, void *data)
441 LASSERT(data != NULL);
443 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
446 int lprocfs_rd_atomic(char *page, char **start, off_t off,
447 int count, int *eof, void *data)
449 atomic_t *atom = data;
450 LASSERT(atom != NULL);
452 return snprintf(page, count, "%d\n", atomic_read(atom));
455 int lprocfs_wr_atomic(struct file *file, const char *buffer,
456 unsigned long count, void *data)
458 atomic_t *atm = data;
462 rc = lprocfs_write_helper(buffer, count, &val);
469 atomic_set(atm, val);
473 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
474 int *eof, void *data)
476 struct obd_device *obd = data;
478 LASSERT(obd != NULL);
480 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
483 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
484 int *eof, void *data)
486 struct obd_device *dev = data;
488 LASSERT(dev != NULL);
489 LASSERT(dev->obd_name != NULL);
491 return snprintf(page, count, "%s\n", dev->obd_name);
494 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
497 struct obd_device *obd = data;
499 LASSERT(obd != NULL);
500 LASSERT(obd->obd_fsops != NULL);
501 LASSERT(obd->obd_fsops->fs_type != NULL);
502 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
505 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
506 int *eof, void *data)
508 struct obd_statfs osfs;
509 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
513 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
518 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
519 int *eof, void *data)
521 struct obd_statfs osfs;
522 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
525 __u32 blk_size = osfs.os_bsize >> 10;
526 __u64 result = osfs.os_blocks;
528 while (blk_size >>= 1)
532 rc = snprintf(page, count, LPU64"\n", result);
537 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
538 int *eof, void *data)
540 struct obd_statfs osfs;
541 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
544 __u32 blk_size = osfs.os_bsize >> 10;
545 __u64 result = osfs.os_bfree;
547 while (blk_size >>= 1)
551 rc = snprintf(page, count, LPU64"\n", result);
556 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
557 int *eof, void *data)
559 struct obd_statfs osfs;
560 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
563 __u32 blk_size = osfs.os_bsize >> 10;
564 __u64 result = osfs.os_bavail;
566 while (blk_size >>= 1)
570 rc = snprintf(page, count, LPU64"\n", result);
575 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
576 int *eof, void *data)
578 struct obd_statfs osfs;
579 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
583 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
589 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
590 int *eof, void *data)
592 struct obd_statfs osfs;
593 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
597 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
602 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
603 int *eof, void *data)
605 struct obd_device *obd = data;
606 struct obd_import *imp;
607 char *imp_state_name = NULL;
610 LASSERT(obd != NULL);
611 LPROCFS_CLIMP_CHECK(obd);
612 imp = obd->u.cli.cl_import;
613 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
615 rc = snprintf(page, count, "%s\t%s%s\n",
616 obd2cli_tgt(obd), imp_state_name,
617 imp->imp_deactive ? "\tDEACTIVATED" : "");
619 LPROCFS_CLIMP_EXIT(obd);
623 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
624 int *eof, void *data)
626 struct obd_device *obd = data;
627 struct ptlrpc_connection *conn;
630 LASSERT(obd != NULL);
632 LPROCFS_CLIMP_CHECK(obd);
633 conn = obd->u.cli.cl_import->imp_connection;
634 LASSERT(conn != NULL);
636 if (obd->u.cli.cl_import) {
637 rc = snprintf(page, count, "%s\n",
638 conn->c_remote_uuid.uuid);
640 rc = snprintf(page, count, "%s\n", "<none>");
643 LPROCFS_CLIMP_EXIT(obd);
647 /** add up per-cpu counters */
648 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
649 struct lprocfs_counter *cnt)
651 unsigned int num_cpu;
652 struct lprocfs_counter t;
653 struct lprocfs_counter *percpu_cntr;
656 memset(cnt, 0, sizeof(*cnt));
659 /* set count to 1 to avoid divide-by-zero errs in callers */
664 cnt->lc_min = LC_MIN_INIT;
666 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
669 num_cpu = num_possible_cpus();
671 for (i = 0; i < num_cpu; i++) {
672 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
675 centry = atomic_read(&percpu_cntr->lc_cntl.la_entry);
676 t.lc_count = percpu_cntr->lc_count;
677 t.lc_sum = percpu_cntr->lc_sum;
678 t.lc_min = percpu_cntr->lc_min;
679 t.lc_max = percpu_cntr->lc_max;
680 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
681 } while (centry != atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
682 centry != atomic_read(&percpu_cntr->lc_cntl.la_exit));
683 cnt->lc_count += t.lc_count;
684 cnt->lc_sum += t.lc_sum;
685 if (t.lc_min < cnt->lc_min)
686 cnt->lc_min = t.lc_min;
687 if (t.lc_max > cnt->lc_max)
688 cnt->lc_max = t.lc_max;
689 cnt->lc_sumsquare += t.lc_sumsquare;
692 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
696 * Append a space separated list of current set flags to str.
698 #define flag2str(flag) \
699 if (imp->imp_##flag && max - len > 0) \
700 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
701 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
705 if (imp->imp_obd->obd_no_recov)
706 len += snprintf(str, max - len, "no_recov");
710 flag2str(replayable);
713 flag2str(last_recon);
718 static const char *obd_connect_names[] = {
745 "mds_mds_connection",
748 "alt_checksum_algorithm",
757 static int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
762 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
764 ret += snprintf(page + ret, count - ret, "%s%s",
765 ret ? sep : "", obd_connect_names[i]);
767 if (flags & ~(mask - 1))
768 ret += snprintf(page + ret, count - ret,
769 "%sunknown flags "LPX64,
770 ret ? sep : "", flags & ~(mask - 1));
774 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
775 int *eof, void *data)
777 struct lprocfs_counter ret;
778 struct obd_device *obd = (struct obd_device *)data;
779 struct obd_import *imp;
782 LASSERT(obd != NULL);
783 LPROCFS_CLIMP_CHECK(obd);
784 imp = obd->u.cli.cl_import;
787 i = snprintf(page, count,
791 " current_connection: %s\n"
796 imp->imp_connection->c_remote_uuid.uuid,
797 ptlrpc_import_state_name(imp->imp_state));
798 i += obd_connect_flags2str(page + i, count - i,
799 imp->imp_connect_data.ocd_connect_flags,
801 i += snprintf(page + i, count - i,
804 i += obd_import_flags2str(imp, page + i, count - i);
806 i += snprintf(page + i, count - i,
809 " connection_attempts: %u\n"
811 " in-progress_invalidations: %u\n",
814 atomic_read(&imp->imp_inval_count));
816 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
817 do_div(ret.lc_sum, ret.lc_count);
818 i += snprintf(page + i, count - i,
821 " unregistering: %u\n"
823 " avg_waittime: "LPU64" %s\n",
824 atomic_read(&imp->imp_inflight),
825 atomic_read(&imp->imp_unregistering),
826 atomic_read(&imp->imp_timeouts),
827 ret.lc_sum, ret.lc_units);
830 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
831 if (imp->imp_at.iat_portal[j] == 0)
833 k = max_t(unsigned int, k,
834 at_get(&imp->imp_at.iat_service_estimate[j]));
836 i += snprintf(page + i, count - i,
837 " service_estimates:\n"
838 " services: %u sec\n"
839 " network: %u sec\n",
841 at_get(&imp->imp_at.iat_net_latency));
843 i += snprintf(page + i, count - i,
845 " last_replay: "LPU64"\n"
846 " peer_committed: "LPU64"\n"
847 " last_checked: "LPU64"\n",
848 imp->imp_last_replay_transno,
849 imp->imp_peer_committed_transno,
850 imp->imp_last_transno_checked);
853 for (rw = 0; rw <= 1; rw++) {
854 lprocfs_stats_collect(obd->obd_svc_stats,
855 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
857 if (ret.lc_sum > 0) {
858 do_div(ret.lc_sum, ret.lc_count);
859 i += snprintf(page + i, count - i,
860 " %s_data_averages:\n"
861 " bytes_per_rpc: "LPU64"\n",
862 rw ? "write" : "read",
866 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
867 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
868 if (ret.lc_sum > 0) {
869 do_div(ret.lc_sum, ret.lc_count);
870 i += snprintf(page + i, count - i,
871 " %s_per_rpc: "LPU64"\n",
872 ret.lc_units, ret.lc_sum);
875 i += snprintf(page + i, count - i,
876 " MB_per_sec: %u.%.02u\n",
877 k / j, (100 * k / j) % 100);
881 LPROCFS_CLIMP_EXIT(obd);
885 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
886 int *eof, void *data)
888 struct obd_device *obd = (struct obd_device *)data;
889 struct obd_import *imp;
892 LASSERT(obd != NULL);
893 LPROCFS_CLIMP_CHECK(obd);
894 imp = obd->u.cli.cl_import;
897 i = snprintf(page, count, "current_state: %s\n",
898 ptlrpc_import_state_name(imp->imp_state));
899 i += snprintf(page + i, count - i,
901 k = imp->imp_state_hist_idx;
902 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
903 struct import_state_hist *ish =
904 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
905 if (ish->ish_state == 0)
907 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
909 ptlrpc_import_state_name(ish->ish_state));
912 LPROCFS_CLIMP_EXIT(obd);
916 int lprocfs_at_hist_helper(char *page, int count, int rc,
917 struct adaptive_timeout *at)
920 for (i = 0; i < AT_BINS; i++)
921 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
922 rc += snprintf(page + rc, count - rc, "\n");
926 int lprocfs_rd_quota_resend_count(char *page, char **start, off_t off,
927 int count, int *eof, void *data)
929 struct obd_device *obd = data;
931 return snprintf(page, count, "%u\n",
932 atomic_read(&obd->u.cli.cl_quota_resends));
935 int lprocfs_wr_quota_resend_count(struct file *file, const char *buffer,
936 unsigned long count, void *data)
938 struct obd_device *obd = data;
941 rc = lprocfs_write_helper(buffer, count, &val);
948 atomic_set(&obd->u.cli.cl_quota_resends, val);
953 /* See also ptlrpc_lprocfs_rd_timeouts */
954 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
955 int *eof, void *data)
957 struct obd_device *obd = (struct obd_device *)data;
958 struct obd_import *imp;
959 unsigned int cur, worst;
964 LASSERT(obd != NULL);
965 LPROCFS_CLIMP_CHECK(obd);
966 imp = obd->u.cli.cl_import;
969 now = cfs_time_current_sec();
971 /* Some network health info for kicks */
972 s2dhms(&ts, now - imp->imp_last_reply_time);
973 rc += snprintf(page + rc, count - rc,
974 "%-10s : %ld, "DHMS_FMT" ago\n",
975 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
977 cur = at_get(&imp->imp_at.iat_net_latency);
978 worst = imp->imp_at.iat_net_latency.at_worst_ever;
979 worstt = imp->imp_at.iat_net_latency.at_worst_time;
980 s2dhms(&ts, now - worstt);
981 rc += snprintf(page + rc, count - rc,
982 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
983 "network", cur, worst, worstt, DHMS_VARS(&ts));
984 rc = lprocfs_at_hist_helper(page, count, rc,
985 &imp->imp_at.iat_net_latency);
987 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
988 if (imp->imp_at.iat_portal[i] == 0)
990 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
991 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
992 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
993 s2dhms(&ts, now - worstt);
994 rc += snprintf(page + rc, count - rc,
995 "portal %-2d : cur %3u worst %3u (at %ld, "
996 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
997 cur, worst, worstt, DHMS_VARS(&ts));
998 rc = lprocfs_at_hist_helper(page, count, rc,
999 &imp->imp_at.iat_service_estimate[i]);
1002 LPROCFS_CLIMP_EXIT(obd);
1006 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1007 int count, int *eof, void *data)
1009 struct obd_device *obd = data;
1013 LPROCFS_CLIMP_CHECK(obd);
1014 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1015 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1016 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1017 ret += snprintf(page + ret, count - ret, "\n");
1018 LPROCFS_CLIMP_EXIT(obd);
1021 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1023 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1024 int *eof, void *data)
1026 struct obd_device *obd = data;
1028 LASSERT(obd != NULL);
1030 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1033 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1034 int *eof, void *data)
1036 struct obd_type *class = (struct obd_type*) data;
1038 LASSERT(class != NULL);
1040 return snprintf(page, count, "%d\n", class->typ_refcnt);
1043 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1047 LASSERT(obd != NULL);
1048 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1049 LASSERT(obd->obd_type->typ_procroot != NULL);
1051 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1052 obd->obd_type->typ_procroot,
1054 if (IS_ERR(obd->obd_proc_entry)) {
1055 rc = PTR_ERR(obd->obd_proc_entry);
1056 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1057 obd->obd_proc_entry = NULL;
1062 int lprocfs_obd_cleanup(struct obd_device *obd)
1066 if (obd->obd_proc_exports_entry) {
1067 /* Should be no exports left */
1068 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1069 lprocfs_remove(&obd->obd_proc_exports_entry);
1070 obd->obd_proc_exports_entry = NULL;
1072 if (obd->obd_proc_entry) {
1073 lprocfs_remove(&obd->obd_proc_entry);
1074 obd->obd_proc_entry = NULL;
1079 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1081 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1082 client_stat->nid_proc, client_stat->nid_stats,
1083 client_stat->nid_brw_stats);
1085 LASSERTF(atomic_read(&client_stat->nid_exp_ref_count) == 0,
1086 "count %d\n", atomic_read(&client_stat->nid_exp_ref_count));
1088 hlist_del_init(&client_stat->nid_hash);
1090 if (client_stat->nid_proc)
1091 lprocfs_remove(&client_stat->nid_proc);
1093 if (client_stat->nid_stats)
1094 lprocfs_free_stats(&client_stat->nid_stats);
1096 if (client_stat->nid_brw_stats)
1097 OBD_FREE_PTR(client_stat->nid_brw_stats);
1099 if (client_stat->nid_ldlm_stats)
1100 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1102 OBD_FREE_PTR(client_stat);
1107 void lprocfs_free_per_client_stats(struct obd_device *obd)
1109 struct nid_stat *stat;
1112 /* we need extra list - because hash_exit called to early */
1113 /* not need locking because all clients is died */
1114 while(!list_empty(&obd->obd_nid_stats)) {
1115 stat = list_entry(obd->obd_nid_stats.next,
1116 struct nid_stat, nid_list);
1117 list_del_init(&stat->nid_list);
1118 lprocfs_free_client_stats(stat);
1124 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1125 enum lprocfs_stats_flags flags)
1127 struct lprocfs_stats *stats;
1128 unsigned int percpusize;
1130 unsigned int num_cpu;
1135 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1138 num_cpu = num_possible_cpus();
1140 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1144 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1145 stats->ls_flags = flags;
1146 spin_lock_init(&stats->ls_lock);
1147 /* Use this lock only if there are no percpu areas */
1149 stats->ls_flags = 0;
1152 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1154 percpusize = L1_CACHE_ALIGN(percpusize);
1156 for (i = 0; i < num_cpu; i++) {
1157 OBD_ALLOC(stats->ls_percpu[i], percpusize);
1158 if (stats->ls_percpu[i] == NULL) {
1159 for (j = 0; j < i; j++) {
1160 OBD_FREE(stats->ls_percpu[j], percpusize);
1161 stats->ls_percpu[j] = NULL;
1166 if (stats->ls_percpu[0] == NULL) {
1167 OBD_FREE(stats, offsetof(typeof(*stats),
1168 ls_percpu[num_cpu]));
1172 stats->ls_num = num;
1176 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1178 struct lprocfs_stats *stats = *statsh;
1179 unsigned int num_cpu;
1180 unsigned int percpusize;
1183 if (stats == NULL || stats->ls_num == 0)
1187 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1190 num_cpu = num_possible_cpus();
1192 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1194 percpusize = L1_CACHE_ALIGN(percpusize);
1195 for (i = 0; i < num_cpu; i++)
1196 OBD_FREE(stats->ls_percpu[i], percpusize);
1197 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1200 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1202 struct lprocfs_counter *percpu_cntr;
1204 unsigned int num_cpu;
1206 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1208 for (i = 0; i < num_cpu; i++) {
1209 for (j = 0; j < stats->ls_num; j++) {
1210 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1211 atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1212 percpu_cntr->lc_count = 0;
1213 percpu_cntr->lc_sum = 0;
1214 percpu_cntr->lc_min = LC_MIN_INIT;
1215 percpu_cntr->lc_max = 0;
1216 percpu_cntr->lc_sumsquare = 0;
1217 atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1221 lprocfs_stats_unlock(stats);
1224 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1225 size_t len, loff_t *off)
1227 struct seq_file *seq = file->private_data;
1228 struct lprocfs_stats *stats = seq->private;
1230 lprocfs_clear_stats(stats);
1235 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1237 struct lprocfs_stats *stats = p->private;
1238 /* return 1st cpu location */
1239 return (*pos >= stats->ls_num) ? NULL :
1240 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1243 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1247 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1249 struct lprocfs_stats *stats = p->private;
1251 return (*pos >= stats->ls_num) ? NULL :
1252 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1255 /* seq file export of one lprocfs counter */
1256 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1258 struct lprocfs_stats *stats = p->private;
1259 struct lprocfs_counter *cntr = v;
1260 struct lprocfs_counter ret;
1263 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1265 do_gettimeofday(&now);
1266 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1267 "snapshot_time", now.tv_sec, now.tv_usec);
1271 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1273 lprocfs_stats_collect(stats, idx, &ret);
1275 if (ret.lc_count == 0)
1278 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1279 ret.lc_count, cntr->lc_units);
1284 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1285 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1286 ret.lc_min, ret.lc_max, ret.lc_sum);
1289 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1290 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1294 rc = seq_printf(p, "\n");
1296 return (rc < 0) ? rc : 0;
1299 struct seq_operations lprocfs_stats_seq_sops = {
1300 start: lprocfs_stats_seq_start,
1301 stop: lprocfs_stats_seq_stop,
1302 next: lprocfs_stats_seq_next,
1303 show: lprocfs_stats_seq_show,
1306 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1308 struct proc_dir_entry *dp = PDE(inode);
1309 struct seq_file *seq;
1312 LPROCFS_ENTRY_AND_CHECK(dp);
1313 rc = seq_open(file, &lprocfs_stats_seq_sops);
1318 seq = file->private_data;
1319 seq->private = dp->data;
1323 struct file_operations lprocfs_stats_seq_fops = {
1324 .owner = THIS_MODULE,
1325 .open = lprocfs_stats_seq_open,
1327 .write = lprocfs_stats_seq_write,
1328 .llseek = seq_lseek,
1329 .release = lprocfs_seq_release,
1332 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1333 struct lprocfs_stats *stats)
1335 struct proc_dir_entry *entry;
1336 LASSERT(root != NULL);
1338 entry = create_proc_entry(name, 0644, root);
1341 entry->proc_fops = &lprocfs_stats_seq_fops;
1342 entry->data = stats;
1346 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1347 unsigned conf, const char *name, const char *units)
1349 struct lprocfs_counter *c;
1351 unsigned int num_cpu;
1353 LASSERT(stats != NULL);
1355 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1357 for (i = 0; i < num_cpu; i++) {
1358 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1359 c->lc_config = conf;
1362 c->lc_min = LC_MIN_INIT;
1365 c->lc_units = units;
1368 lprocfs_stats_unlock(stats);
1370 EXPORT_SYMBOL(lprocfs_counter_init);
1372 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1374 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1375 LASSERT(coffset < stats->ls_num); \
1376 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1379 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1381 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1382 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1383 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1384 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1385 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1386 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1387 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1388 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1389 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1390 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1391 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1392 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1393 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1394 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1395 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1396 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1397 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1398 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1399 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1400 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1401 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1402 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1403 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1404 LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd);
1405 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1406 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1407 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1408 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1409 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1410 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1411 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1412 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1413 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1414 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1415 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1416 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1417 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1418 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1419 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1420 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1421 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1422 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1423 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1424 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1425 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1426 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1427 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1428 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1429 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1430 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1431 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1432 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1433 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1434 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1435 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1436 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1437 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1438 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1439 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1440 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1441 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1442 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1443 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1444 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1445 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1446 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1447 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1448 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1449 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1452 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1454 struct lprocfs_stats *stats;
1455 unsigned int num_stats;
1458 LASSERT(obd->obd_stats == NULL);
1459 LASSERT(obd->obd_proc_entry != NULL);
1460 LASSERT(obd->obd_cntr_base == 0);
1462 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1463 num_private_stats - 1 /* o_owner */;
1464 stats = lprocfs_alloc_stats(num_stats, 0);
1468 lprocfs_init_ops_stats(num_private_stats, stats);
1470 for (i = num_private_stats; i < num_stats; i++) {
1471 /* If this LBUGs, it is likely that an obd
1472 * operation was added to struct obd_ops in
1473 * <obd.h>, and that the corresponding line item
1474 * LPROCFS_OBD_OP_INIT(.., .., opname)
1475 * is missing from the list above. */
1476 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1477 "Missing obd_stat initializer obd_op "
1478 "operation at offset %d.\n", i - num_private_stats);
1480 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1482 lprocfs_free_stats(&stats);
1484 obd->obd_stats = stats;
1485 obd->obd_cntr_base = num_private_stats;
1490 void lprocfs_free_obd_stats(struct obd_device *obd)
1493 lprocfs_free_stats(&obd->obd_stats);
1496 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1498 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1499 LASSERT(coffset < stats->ls_num); \
1500 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1503 int lprocfs_alloc_md_stats(struct obd_device *obd,
1504 unsigned num_private_stats)
1506 struct lprocfs_stats *stats;
1507 unsigned int num_stats;
1510 LASSERT(obd->md_stats == NULL);
1511 LASSERT(obd->obd_proc_entry != NULL);
1512 LASSERT(obd->md_cntr_base == 0);
1514 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1516 stats = lprocfs_alloc_stats(num_stats, 0);
1520 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1521 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1522 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1523 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1524 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1525 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1526 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1527 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1528 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1529 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1530 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1531 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1532 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1533 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1534 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1535 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1536 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1537 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1538 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1539 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1540 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1541 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1542 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1543 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1544 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1545 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1546 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1547 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1548 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1549 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1550 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1552 for (i = num_private_stats; i < num_stats; i++) {
1553 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1554 CERROR("Missing md_stat initializer md_op "
1555 "operation at offset %d. Aborting.\n",
1556 i - num_private_stats);
1560 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1562 lprocfs_free_stats(&stats);
1564 obd->md_stats = stats;
1565 obd->md_cntr_base = num_private_stats;
1570 void lprocfs_free_md_stats(struct obd_device *obd)
1572 struct lprocfs_stats *stats = obd->md_stats;
1574 if (stats != NULL) {
1575 obd->md_stats = NULL;
1576 obd->md_cntr_base = 0;
1577 lprocfs_free_stats(&stats);
1581 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1583 lprocfs_counter_init(ldlm_stats,
1584 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1585 0, "ldlm_enqueue", "reqs");
1586 lprocfs_counter_init(ldlm_stats,
1587 LDLM_CONVERT - LDLM_FIRST_OPC,
1588 0, "ldlm_convert", "reqs");
1589 lprocfs_counter_init(ldlm_stats,
1590 LDLM_CANCEL - LDLM_FIRST_OPC,
1591 0, "ldlm_cancel", "reqs");
1592 lprocfs_counter_init(ldlm_stats,
1593 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1594 0, "ldlm_bl_callback", "reqs");
1595 lprocfs_counter_init(ldlm_stats,
1596 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1597 0, "ldlm_cp_callback", "reqs");
1598 lprocfs_counter_init(ldlm_stats,
1599 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1600 0, "ldlm_gl_callback", "reqs");
1603 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1604 int *eof, void *data)
1606 struct obd_export *exp = data;
1607 LASSERT(exp != NULL);
1609 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1612 struct exp_uuid_cb_data {
1620 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1621 int count, int *eof, int *len)
1623 cb_data->page = page;
1624 cb_data->count = count;
1629 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1631 struct obd_export *exp = (struct obd_export *)obj;
1632 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1634 if (exp->exp_nid_stats)
1635 *data->len += snprintf((data->page + *data->len),
1636 data->count, "%s\n",
1637 obd_uuid2str(&exp->exp_client_uuid));
1640 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1641 int *eof, void *data)
1643 struct nid_stat *stats = (struct nid_stat *)data;
1644 struct exp_uuid_cb_data cb_data;
1645 struct obd_device *obd = stats->nid_obd;
1650 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1651 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1652 lprocfs_exp_print_uuid, &cb_data);
1653 return (*cb_data.len);
1656 void lprocfs_exp_print_hash(void *obj, void *cb_data)
1658 struct exp_uuid_cb_data *data = cb_data;
1659 struct obd_export *exp = obj;
1662 lh = exp->exp_lock_hash;
1665 *data->len += lustre_hash_debug_header(data->page,
1668 *data->len += lustre_hash_debug_str(lh, data->page + *data->len,
1673 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1674 int *eof, void *data)
1676 struct nid_stat *stats = (struct nid_stat *)data;
1677 struct exp_uuid_cb_data cb_data;
1678 struct obd_device *obd = stats->nid_obd;
1683 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1685 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1686 lprocfs_exp_print_hash, &cb_data);
1687 return (*cb_data.len);
1690 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1691 int count, int *eof, void *data)
1694 return snprintf(page, count, "%s\n",
1695 "Write into this file to clear all nid stats and "
1696 "stale nid entries");
1698 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1700 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1702 struct nid_stat *stat = obj;
1705 /* object has only hash + iterate_all references.
1706 * add/delete blocked by hash bucket lock */
1707 CDEBUG(D_INFO,"refcnt %d\n", atomic_read(&stat->nid_exp_ref_count));
1708 if (atomic_read(&stat->nid_exp_ref_count) == 2) {
1709 hlist_del_init(&stat->nid_hash);
1710 nidstat_putref(stat);
1711 spin_lock(&stat->nid_obd->obd_nid_lock);
1712 list_move(&stat->nid_list, data);
1713 spin_unlock(&stat->nid_obd->obd_nid_lock);
1717 /* we has reference to object - only clear data*/
1718 if (stat->nid_stats)
1719 lprocfs_clear_stats(stat->nid_stats);
1721 if (stat->nid_brw_stats) {
1722 for (i = 0; i < BRW_LAST; i++)
1723 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1729 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1730 unsigned long count, void *data)
1732 struct obd_device *obd = (struct obd_device *)data;
1733 struct nid_stat *client_stat;
1734 CFS_LIST_HEAD(free_list);
1736 lustre_hash_for_each(obd->obd_nid_stats_hash,
1737 lprocfs_nid_stats_clear_write_cb, &free_list);
1739 while (!list_empty(&free_list)) {
1740 client_stat = list_entry(free_list.next, struct nid_stat,
1742 list_del_init(&client_stat->nid_list);
1743 lprocfs_free_client_stats(client_stat);
1748 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1750 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1752 struct nid_stat *new_stat, *old_stat;
1753 struct obd_device *obd = NULL;
1754 cfs_proc_dir_entry_t *entry;
1760 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1761 !exp->exp_obd->obd_nid_stats_hash)
1764 /* not test against zero because eric say:
1765 * You may only test nid against another nid, or LNET_NID_ANY.
1766 * Anything else is nonsense.*/
1767 if (!nid || *nid == LNET_NID_ANY)
1772 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1774 OBD_ALLOC_PTR(new_stat);
1775 if (new_stat == NULL)
1778 new_stat->nid = *nid;
1779 new_stat->nid_obd = exp->exp_obd;
1780 atomic_set(&new_stat->nid_exp_ref_count, 0);
1782 old_stat = lustre_hash_findadd_unique(obd->obd_nid_stats_hash,
1783 nid, &new_stat->nid_hash);
1784 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1785 old_stat, libcfs_nid2str(*nid),
1786 atomic_read(&new_stat->nid_exp_ref_count));
1788 /* Return -EALREADY here so that we know that the /proc
1789 * entry already has been created */
1790 if (old_stat != new_stat) {
1791 spin_lock(&obd->obd_nid_lock);
1792 if (exp->exp_nid_stats != old_stat) {
1793 if (exp->exp_nid_stats)
1794 nidstat_putref(exp->exp_nid_stats);
1795 exp->exp_nid_stats = old_stat;
1797 /* lustre_hash_findadd_unique() has added
1798 * old_stat's refcount */
1799 nidstat_putref(old_stat);
1802 spin_unlock(&obd->obd_nid_lock);
1804 GOTO(destroy_new, rc = -EALREADY);
1806 /* not found - create */
1807 new_stat->nid_proc = lprocfs_register(libcfs_nid2str(*nid),
1808 obd->obd_proc_exports_entry,
1810 if (new_stat->nid_proc == NULL) {
1811 CERROR("Error making export directory for nid %s\n",
1812 libcfs_nid2str(*nid));
1813 GOTO(destroy_new_ns, rc = -ENOMEM);
1816 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1817 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1818 if (IS_ERR(entry)) {
1819 CWARN("Error adding the NID stats file\n");
1820 rc = PTR_ERR(entry);
1821 GOTO(destroy_new_ns, rc);
1824 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1825 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1826 if (IS_ERR(entry)) {
1827 CWARN("Error adding the hash file\n");
1828 rc = PTR_ERR(entry);
1829 GOTO(destroy_new_ns, rc);
1832 if (exp->exp_nid_stats)
1833 nidstat_putref(exp->exp_nid_stats);
1834 nidstat_getref(new_stat);
1835 exp->exp_nid_stats = new_stat;
1837 /* protect competitive add to list, not need locking on destroy */
1838 spin_lock(&obd->obd_nid_lock);
1839 list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1840 spin_unlock(&obd->obd_nid_lock);
1845 if (new_stat->nid_proc != NULL)
1846 lprocfs_remove(&new_stat->nid_proc);
1847 lustre_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1850 OBD_FREE_PTR(new_stat);
1854 int lprocfs_exp_cleanup(struct obd_export *exp)
1856 struct nid_stat *stat = exp->exp_nid_stats;
1858 if(!stat || !exp->exp_obd)
1861 nidstat_putref(exp->exp_nid_stats);
1862 exp->exp_nid_stats = NULL;
1863 lprocfs_free_md_stats(exp->exp_obd);
1868 int lprocfs_write_helper(const char *buffer, unsigned long count,
1871 return lprocfs_write_frac_helper(buffer, count, val, 1);
1874 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1877 char kernbuf[20], *end, *pbuf;
1879 if (count > (sizeof(kernbuf) - 1))
1882 if (copy_from_user(kernbuf, buffer, count))
1885 kernbuf[count] = '\0';
1892 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1896 if (end != NULL && *end == '.') {
1897 int temp_val, pow = 1;
1901 if (strlen(pbuf) > 5)
1902 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1904 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1907 for (i = 0; i < (end - pbuf); i++)
1910 *val += temp_val / pow;
1916 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
1919 long decimal_val, frac_val;
1925 decimal_val = val / mult;
1926 prtn = snprintf(buffer, count, "%ld", decimal_val);
1927 frac_val = val % mult;
1929 if (prtn < (count - 4) && frac_val > 0) {
1931 int i, temp_mult = 1, frac_bits = 0;
1933 temp_frac = frac_val * 10;
1934 buffer[prtn++] = '.';
1935 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
1936 /* only reserved 2 bits fraction */
1937 buffer[prtn++] ='0';
1942 * Need to think these cases :
1943 * 1. #echo x.00 > /proc/xxx output result : x
1944 * 2. #echo x.0x > /proc/xxx output result : x.0x
1945 * 3. #echo x.x0 > /proc/xxx output result : x.x
1946 * 4. #echo x.xx > /proc/xxx output result : x.xx
1947 * Only reserved 2 bits fraction.
1949 for (i = 0; i < (5 - prtn); i++)
1952 frac_bits = min((int)count - prtn, 3 - frac_bits);
1953 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
1954 frac_val * temp_mult / mult);
1957 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1959 if (buffer[prtn] == '.') {
1966 buffer[prtn++] ='\n';
1970 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1972 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1975 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1976 __u64 *val, int mult)
1978 char kernbuf[22], *end, *pbuf;
1979 __u64 whole, frac = 0, units;
1980 unsigned frac_d = 1;
1982 if (count > (sizeof(kernbuf) - 1))
1985 if (copy_from_user(kernbuf, buffer, count))
1988 kernbuf[count] = '\0';
1995 whole = simple_strtoull(pbuf, &end, 10);
1999 if (end != NULL && *end == '.') {
2003 /* need to limit frac_d to a __u32 */
2004 if (strlen(pbuf) > 10)
2007 frac = simple_strtoull(pbuf, &end, 10);
2008 /* count decimal places */
2009 for (i = 0; i < (end - pbuf); i++)
2026 /* Specified units override the multiplier */
2028 mult = mult < 0 ? -units : units;
2031 do_div(frac, frac_d);
2032 *val = whole * mult + frac;
2036 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2037 struct file_operations *seq_fops, void *data)
2039 struct proc_dir_entry *entry;
2042 entry = create_proc_entry(name, mode, parent);
2045 entry->proc_fops = seq_fops;
2050 EXPORT_SYMBOL(lprocfs_seq_create);
2052 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2054 struct file_operations *seq_fops,
2057 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2058 mode, seq_fops, data));
2060 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2062 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2064 if (value >= OBD_HIST_MAX)
2065 value = OBD_HIST_MAX - 1;
2067 spin_lock(&oh->oh_lock);
2068 oh->oh_buckets[value]++;
2069 spin_unlock(&oh->oh_lock);
2071 EXPORT_SYMBOL(lprocfs_oh_tally);
2073 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2077 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2080 lprocfs_oh_tally(oh, val);
2082 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2084 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2086 unsigned long ret = 0;
2089 for (i = 0; i < OBD_HIST_MAX; i++)
2090 ret += oh->oh_buckets[i];
2093 EXPORT_SYMBOL(lprocfs_oh_sum);
2095 void lprocfs_oh_clear(struct obd_histogram *oh)
2097 spin_lock(&oh->oh_lock);
2098 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2099 spin_unlock(&oh->oh_lock);
2101 EXPORT_SYMBOL(lprocfs_oh_clear);
2103 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2104 int count, int *eof, void *data)
2106 struct obd_device *obd = data;
2112 c += lustre_hash_debug_header(page, count);
2113 c += lustre_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2114 c += lustre_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2115 c += lustre_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2119 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2121 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2122 int count, int *eof, void *data)
2124 struct obd_device *obd = data;
2127 LASSERT(obd != NULL);
2128 LASSERT(count >= 0);
2130 /* Set start of user data returned to
2131 page + off since the user may have
2132 requested to read much smaller than
2133 what we need to read */
2134 *start = page + off;
2136 /* We know we are allocated a page here.
2137 Also we know that this function will
2138 not need to write more than a page
2139 so we can truncate at CFS_PAGE_SIZE. */
2140 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2142 /* Initialize the page */
2143 memset(page, 0, size);
2145 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2147 if (obd->obd_max_recoverable_clients == 0) {
2148 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2154 /* sampled unlocked, but really... */
2155 if (obd->obd_recovering == 0) {
2156 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2158 if (lprocfs_obd_snprintf(&page, size, &len,
2159 "recovery_start: %lu\n",
2160 obd->obd_recovery_start) <= 0)
2162 if (lprocfs_obd_snprintf(&page, size, &len,
2163 "recovery_duration: %lu\n",
2164 obd->obd_recovery_end -
2165 obd->obd_recovery_start) <= 0)
2167 /* Number of clients that have completed recovery */
2168 if (lprocfs_obd_snprintf(&page, size, &len,
2169 "completed_clients: %d/%d\n",
2170 obd->obd_max_recoverable_clients -
2171 obd->obd_stale_clients,
2172 obd->obd_max_recoverable_clients) <= 0)
2174 if (lprocfs_obd_snprintf(&page, size, &len,
2175 "replayed_requests: %d\n",
2176 obd->obd_replayed_requests) <= 0)
2178 if (lprocfs_obd_snprintf(&page, size, &len,
2179 "last_transno: "LPD64"\n",
2180 obd->obd_next_recovery_transno - 1)<=0)
2182 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2183 obd->obd_version_recov ? "ON" : "OFF")<=0)
2188 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2190 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2191 obd->obd_recovery_start) <= 0)
2193 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2194 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2195 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2197 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2198 obd->obd_connected_clients,
2199 obd->obd_max_recoverable_clients) <= 0)
2201 /* Number of clients that have completed recovery */
2202 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2203 atomic_read(&obd->obd_req_replay_clients))<= 0)
2205 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2206 atomic_read(&obd->obd_lock_replay_clients))<=0)
2208 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2209 obd->obd_connected_clients -
2210 atomic_read(&obd->obd_lock_replay_clients))<=0)
2212 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2213 obd->obd_stale_clients) <= 0)
2215 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2216 obd->obd_replayed_requests) <= 0)
2218 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2219 obd->obd_requests_queued_for_recovery) <= 0)
2222 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2223 obd->obd_next_recovery_transno) <= 0)
2229 return min(count, len - (int)off);
2231 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2233 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
2234 int count, int *eof, void *data)
2236 struct obd_device *obd = data;
2237 LASSERT(obd != NULL);
2239 return snprintf(page, count, "%lu\n", obd->obd_recovery_max_time);
2241 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
2243 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
2244 unsigned long count, void *data)
2246 struct obd_device *obd = data;
2248 LASSERT(obd != NULL);
2250 rc = lprocfs_write_helper(buffer, count, &val);
2254 obd->obd_recovery_max_time = val;
2257 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
2260 /**** Changelogs *****/
2261 #define D_CHANGELOG 0
2263 /* How many records per seq_show. Too small, we spawn llog_process threads
2264 too often; too large, we run out of buffer space */
2265 #define CHANGELOG_CHUNK_SIZE 100
2267 static int changelog_show_cb(struct llog_handle *llh, struct llog_rec_hdr *hdr,
2270 struct seq_file *seq = (struct seq_file *)data;
2271 struct changelog_seq_iter *csi = seq->private;
2272 struct llog_changelog_rec *rec = (struct llog_changelog_rec *)hdr;
2277 if ((rec->cr_hdr.lrh_type != CHANGELOG_REC) ||
2278 (rec->cr.cr_type >= CL_LAST)) {
2279 CERROR("Not a changelog rec %d/%d\n", rec->cr_hdr.lrh_type,
2284 CDEBUG(D_CHANGELOG, "rec="LPU64" start="LPU64" cat=%d:%d start=%d:%d\n",
2285 rec->cr.cr_index, csi->csi_startrec,
2286 llh->lgh_hdr->llh_cat_idx, llh->lgh_cur_idx,
2287 csi->csi_startcat, csi->csi_startidx);
2289 if (rec->cr.cr_index < csi->csi_startrec)
2290 /* Skip entries earlier than what we are interested in */
2292 if (rec->cr.cr_index == csi->csi_startrec) {
2293 /* Remember where we started, since seq_read will re-read
2294 * the data when it reallocs space. Sigh, if only there was
2295 * a way to tell seq_file how big the buf should be in the
2298 csi->csi_startcat = llh->lgh_hdr->llh_cat_idx;
2299 csi->csi_startidx = rec->cr_hdr.lrh_index - 1;
2301 if (csi->csi_wrote > CHANGELOG_CHUNK_SIZE) {
2302 /* Stop at some point with a reasonable seq_file buffer size.
2303 * Start from here the next time.
2305 csi->csi_endrec = rec->cr.cr_index - 1;
2306 csi->csi_startcat = llh->lgh_hdr->llh_cat_idx;
2307 csi->csi_startidx = rec->cr_hdr.lrh_index - 1;
2309 RETURN(LLOG_PROC_BREAK);
2312 CDEBUG(D_CHANGELOG, LPU64" %02d%-5s "LPU64" 0x%x t="DFID" p="DFID
2313 " %.*s\n", rec->cr.cr_index, rec->cr.cr_type,
2314 changelog_type2str(rec->cr.cr_type), rec->cr.cr_time,
2315 rec->cr.cr_flags & CLF_FLAGMASK,
2316 PFID(&rec->cr.cr_tfid), PFID(&rec->cr.cr_pfid),
2317 rec->cr.cr_namelen, rec->cr.cr_name);
2319 cnt = sizeof(rec->cr) + rec->cr.cr_namelen;
2320 ptr = (char *)(&rec->cr);
2321 CDEBUG(D_CHANGELOG, "packed rec %d starting at %p\n", cnt, ptr);
2323 while ((cnt-- > 0) && (rc == 0)) {
2324 rc = seq_putc(seq, *ptr);
2329 /* Ran out of room in the seq buffer. seq_read will dump
2330 * the whole buffer and re-seq_start with a larger one;
2331 * no point in continuing the llog_process */
2332 CDEBUG(D_CHANGELOG, "rec="LPU64" overflow "LPU64"<-"LPU64"\n",
2333 rec->cr.cr_index, csi->csi_startrec, csi->csi_endrec);
2334 csi->csi_endrec = csi->csi_startrec - 1;
2336 RETURN(LLOG_PROC_BREAK);
2340 csi->csi_endrec = rec->cr.cr_index;
2345 static int changelog_seq_show(struct seq_file *seq, void *v)
2347 struct changelog_seq_iter *csi = seq->private;
2351 if (csi->csi_fill) {
2352 /* seq_read wants more data to fill his buffer. But we already
2353 filled the buf as much as we cared to; force seq_read to
2354 accept that by padding with 0's */
2355 while (seq_putc(seq, 0) == 0);
2359 /* Since we have to restart the llog_cat_process for each chunk of the
2360 seq_ functions, start from where we left off. */
2361 rc = llog_cat_process(csi->csi_llh, changelog_show_cb, seq,
2362 csi->csi_startcat, csi->csi_startidx);
2364 CDEBUG(D_CHANGELOG,"seq_show "LPU64"-"LPU64" cat=%d:%d wrote=%d rc=%d\n",
2365 csi->csi_startrec, csi->csi_endrec, csi->csi_startcat,
2366 csi->csi_startidx, csi->csi_wrote, rc);
2370 if (rc == LLOG_PROC_BREAK)
2371 /* more records left, but seq_show must return 0 */
2376 static void *changelog_seq_start(struct seq_file *seq, loff_t *pos)
2378 struct changelog_seq_iter *csi = seq->private;
2381 CDEBUG(D_CHANGELOG, "start "LPU64"-"LPU64" pos="LPU64"\n",
2382 csi->csi_startrec, csi->csi_endrec, *pos);
2387 /* no more records, seq_read should return 0 if buffer
2391 if (*pos > csi->csi_pos) {
2392 /* The seq_read implementation sucks. It may call start
2393 multiple times, using pos to indicate advances, if any,
2394 by arbitrarily increasing it by 1. So ignore the actual
2395 value of pos, and just register any increase as
2396 "seq_read wants the next values". */
2397 csi->csi_startrec = csi->csi_endrec + 1;
2398 csi->csi_pos = *pos;
2400 /* else use old startrec/startidx */
2405 static void changelog_seq_stop(struct seq_file *seq, void *v)
2407 struct changelog_seq_iter *csi = seq->private;
2409 CDEBUG(D_CHANGELOG, "stop "LPU64"-"LPU64"\n",
2410 csi->csi_startrec, csi->csi_endrec);
2413 static void *changelog_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2415 struct changelog_seq_iter *csi = seq->private;
2417 CDEBUG(D_CHANGELOG, "next "LPU64"-"LPU64" pos="LPU64"\n",
2418 csi->csi_startrec, csi->csi_endrec, *pos);
2425 static struct seq_operations changelog_sops = {
2426 .start = changelog_seq_start,
2427 .stop = changelog_seq_stop,
2428 .next = changelog_seq_next,
2429 .show = changelog_seq_show,
2432 int changelog_seq_open(struct inode *inode, struct file *file,
2433 struct changelog_seq_iter **csih)
2435 struct changelog_seq_iter *csi;
2436 struct proc_dir_entry *dp = PDE(inode);
2437 struct seq_file *seq;
2440 LPROCFS_ENTRY_AND_CHECK(dp);
2442 rc = seq_open(file, &changelog_sops);
2450 lprocfs_seq_release(inode, file);
2454 csi->csi_dev = dp->data;
2455 seq = file->private_data;
2461 EXPORT_SYMBOL(changelog_seq_open);
2463 int changelog_seq_release(struct inode *inode, struct file *file)
2465 struct seq_file *seq = file->private_data;
2466 struct changelog_seq_iter *csi = seq->private;
2471 return lprocfs_seq_release(inode, file);
2473 EXPORT_SYMBOL(changelog_seq_release);
2475 #ifndef SEEK_CUR /* SLES10 needs this */
2480 loff_t changelog_seq_lseek(struct file *file, loff_t offset, int origin)
2482 struct seq_file *seq = (struct seq_file *)file->private_data;
2483 struct changelog_seq_iter *csi = seq->private;
2485 CDEBUG(D_CHANGELOG,"seek "LPU64"-"LPU64" off="LPU64":%d fpos="LPU64"\n",
2486 csi->csi_startrec, csi->csi_endrec, offset, origin, file->f_pos);
2492 offset += csi->csi_endrec;
2495 /* we don't know the last rec */
2506 csi->csi_startrec = offset;
2507 csi->csi_endrec = offset ? offset - 1 : 0;
2509 /* drop whatever is left in sucky seq_read's buffer */
2514 file->f_pos = csi->csi_startrec;
2515 return csi->csi_startrec;
2517 EXPORT_SYMBOL(changelog_seq_lseek);
2519 EXPORT_SYMBOL(lprocfs_register);
2520 EXPORT_SYMBOL(lprocfs_srch);
2521 EXPORT_SYMBOL(lprocfs_remove);
2522 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2523 EXPORT_SYMBOL(lprocfs_add_vars);
2524 EXPORT_SYMBOL(lprocfs_obd_setup);
2525 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2526 EXPORT_SYMBOL(lprocfs_add_simple);
2527 EXPORT_SYMBOL(lprocfs_add_symlink);
2528 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2529 EXPORT_SYMBOL(lprocfs_alloc_stats);
2530 EXPORT_SYMBOL(lprocfs_free_stats);
2531 EXPORT_SYMBOL(lprocfs_clear_stats);
2532 EXPORT_SYMBOL(lprocfs_register_stats);
2533 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2534 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2535 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2536 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2537 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2538 EXPORT_SYMBOL(lprocfs_exp_setup);
2539 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2541 EXPORT_SYMBOL(lprocfs_rd_u64);
2542 EXPORT_SYMBOL(lprocfs_rd_atomic);
2543 EXPORT_SYMBOL(lprocfs_wr_atomic);
2544 EXPORT_SYMBOL(lprocfs_rd_uint);
2545 EXPORT_SYMBOL(lprocfs_wr_uint);
2546 EXPORT_SYMBOL(lprocfs_rd_uuid);
2547 EXPORT_SYMBOL(lprocfs_rd_name);
2548 EXPORT_SYMBOL(lprocfs_rd_fstype);
2549 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2550 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2551 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2552 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2553 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2554 EXPORT_SYMBOL(lprocfs_rd_import);
2555 EXPORT_SYMBOL(lprocfs_rd_state);
2556 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2557 EXPORT_SYMBOL(lprocfs_rd_blksize);
2558 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2559 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2560 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2561 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2562 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2563 EXPORT_SYMBOL(lprocfs_rd_quota_resend_count);
2564 EXPORT_SYMBOL(lprocfs_wr_quota_resend_count);
2566 EXPORT_SYMBOL(lprocfs_write_helper);
2567 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2568 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2569 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2570 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2571 EXPORT_SYMBOL(lprocfs_stats_collect);