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 /* See also ptlrpc_lprocfs_rd_timeouts */
927 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
928 int *eof, void *data)
930 struct obd_device *obd = (struct obd_device *)data;
931 struct obd_import *imp;
932 unsigned int cur, worst;
937 LASSERT(obd != NULL);
938 LPROCFS_CLIMP_CHECK(obd);
939 imp = obd->u.cli.cl_import;
942 now = cfs_time_current_sec();
944 /* Some network health info for kicks */
945 s2dhms(&ts, now - imp->imp_last_reply_time);
946 rc += snprintf(page + rc, count - rc,
947 "%-10s : %ld, "DHMS_FMT" ago\n",
948 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
950 cur = at_get(&imp->imp_at.iat_net_latency);
951 worst = imp->imp_at.iat_net_latency.at_worst_ever;
952 worstt = imp->imp_at.iat_net_latency.at_worst_time;
953 s2dhms(&ts, now - worstt);
954 rc += snprintf(page + rc, count - rc,
955 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
956 "network", cur, worst, worstt, DHMS_VARS(&ts));
957 rc = lprocfs_at_hist_helper(page, count, rc,
958 &imp->imp_at.iat_net_latency);
960 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
961 if (imp->imp_at.iat_portal[i] == 0)
963 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
964 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
965 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
966 s2dhms(&ts, now - worstt);
967 rc += snprintf(page + rc, count - rc,
968 "portal %-2d : cur %3u worst %3u (at %ld, "
969 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
970 cur, worst, worstt, DHMS_VARS(&ts));
971 rc = lprocfs_at_hist_helper(page, count, rc,
972 &imp->imp_at.iat_service_estimate[i]);
975 LPROCFS_CLIMP_EXIT(obd);
979 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
980 int count, int *eof, void *data)
982 struct obd_device *obd = data;
986 LPROCFS_CLIMP_CHECK(obd);
987 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
988 ret = snprintf(page, count, "flags="LPX64"\n", flags);
989 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
990 ret += snprintf(page + ret, count - ret, "\n");
991 LPROCFS_CLIMP_EXIT(obd);
994 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
996 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
997 int *eof, void *data)
999 struct obd_device *obd = data;
1001 LASSERT(obd != NULL);
1003 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1006 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1007 int *eof, void *data)
1009 struct obd_type *class = (struct obd_type*) data;
1011 LASSERT(class != NULL);
1013 return snprintf(page, count, "%d\n", class->typ_refcnt);
1016 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1020 LASSERT(obd != NULL);
1021 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1022 LASSERT(obd->obd_type->typ_procroot != NULL);
1024 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1025 obd->obd_type->typ_procroot,
1027 if (IS_ERR(obd->obd_proc_entry)) {
1028 rc = PTR_ERR(obd->obd_proc_entry);
1029 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1030 obd->obd_proc_entry = NULL;
1035 int lprocfs_obd_cleanup(struct obd_device *obd)
1039 if (obd->obd_proc_exports_entry) {
1040 /* Should be no exports left */
1041 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1042 lprocfs_remove(&obd->obd_proc_exports_entry);
1043 obd->obd_proc_exports_entry = NULL;
1045 if (obd->obd_proc_entry) {
1046 lprocfs_remove(&obd->obd_proc_entry);
1047 obd->obd_proc_entry = NULL;
1052 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1054 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1055 client_stat->nid_proc, client_stat->nid_stats,
1056 client_stat->nid_brw_stats);
1058 LASSERTF(client_stat->nid_exp_ref_count == 0, "count %d\n",
1059 client_stat->nid_exp_ref_count);
1061 hlist_del_init(&client_stat->nid_hash);
1063 if (client_stat->nid_proc)
1064 lprocfs_remove(&client_stat->nid_proc);
1066 if (client_stat->nid_stats)
1067 lprocfs_free_stats(&client_stat->nid_stats);
1069 if (client_stat->nid_brw_stats)
1070 OBD_FREE_PTR(client_stat->nid_brw_stats);
1072 if (client_stat->nid_ldlm_stats)
1073 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1075 OBD_FREE_PTR(client_stat);
1080 void lprocfs_free_per_client_stats(struct obd_device *obd)
1082 struct nid_stat *stat;
1085 /* we need extra list - because hash_exit called to early */
1086 /* not need locking because all clients is died */
1087 while(!list_empty(&obd->obd_nid_stats)) {
1088 stat = list_entry(obd->obd_nid_stats.next,
1089 struct nid_stat, nid_list);
1090 list_del_init(&stat->nid_list);
1091 lprocfs_free_client_stats(stat);
1097 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1098 enum lprocfs_stats_flags flags)
1100 struct lprocfs_stats *stats;
1101 unsigned int percpusize;
1103 unsigned int num_cpu;
1108 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1111 num_cpu = num_possible_cpus();
1113 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1117 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1118 stats->ls_flags = flags;
1119 spin_lock_init(&stats->ls_lock);
1120 /* Use this lock only if there are no percpu areas */
1122 stats->ls_flags = 0;
1125 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1127 percpusize = L1_CACHE_ALIGN(percpusize);
1129 for (i = 0; i < num_cpu; i++) {
1130 OBD_ALLOC(stats->ls_percpu[i], percpusize);
1131 if (stats->ls_percpu[i] == NULL) {
1132 for (j = 0; j < i; j++) {
1133 OBD_FREE(stats->ls_percpu[j], percpusize);
1134 stats->ls_percpu[j] = NULL;
1139 if (stats->ls_percpu[0] == NULL) {
1140 OBD_FREE(stats, offsetof(typeof(*stats),
1141 ls_percpu[num_cpu]));
1145 stats->ls_num = num;
1149 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1151 struct lprocfs_stats *stats = *statsh;
1152 unsigned int num_cpu;
1153 unsigned int percpusize;
1156 if (stats == NULL || stats->ls_num == 0)
1160 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1163 num_cpu = num_possible_cpus();
1165 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1167 percpusize = L1_CACHE_ALIGN(percpusize);
1168 for (i = 0; i < num_cpu; i++)
1169 OBD_FREE(stats->ls_percpu[i], percpusize);
1170 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1173 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1175 struct lprocfs_counter *percpu_cntr;
1177 unsigned int num_cpu;
1179 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1181 for (i = 0; i < num_cpu; i++) {
1182 for (j = 0; j < stats->ls_num; j++) {
1183 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1184 atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1185 percpu_cntr->lc_count = 0;
1186 percpu_cntr->lc_sum = 0;
1187 percpu_cntr->lc_min = LC_MIN_INIT;
1188 percpu_cntr->lc_max = 0;
1189 percpu_cntr->lc_sumsquare = 0;
1190 atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1194 lprocfs_stats_unlock(stats);
1197 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1198 size_t len, loff_t *off)
1200 struct seq_file *seq = file->private_data;
1201 struct lprocfs_stats *stats = seq->private;
1203 lprocfs_clear_stats(stats);
1208 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1210 struct lprocfs_stats *stats = p->private;
1211 /* return 1st cpu location */
1212 return (*pos >= stats->ls_num) ? NULL :
1213 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1216 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1220 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1222 struct lprocfs_stats *stats = p->private;
1224 return (*pos >= stats->ls_num) ? NULL :
1225 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1228 /* seq file export of one lprocfs counter */
1229 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1231 struct lprocfs_stats *stats = p->private;
1232 struct lprocfs_counter *cntr = v;
1233 struct lprocfs_counter ret;
1236 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1238 do_gettimeofday(&now);
1239 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1240 "snapshot_time", now.tv_sec, now.tv_usec);
1244 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1246 lprocfs_stats_collect(stats, idx, &ret);
1248 if (ret.lc_count == 0)
1251 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1252 ret.lc_count, cntr->lc_units);
1257 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1258 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1259 ret.lc_min, ret.lc_max, ret.lc_sum);
1262 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1263 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1267 rc = seq_printf(p, "\n");
1269 return (rc < 0) ? rc : 0;
1272 struct seq_operations lprocfs_stats_seq_sops = {
1273 start: lprocfs_stats_seq_start,
1274 stop: lprocfs_stats_seq_stop,
1275 next: lprocfs_stats_seq_next,
1276 show: lprocfs_stats_seq_show,
1279 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1281 struct proc_dir_entry *dp = PDE(inode);
1282 struct seq_file *seq;
1285 LPROCFS_ENTRY_AND_CHECK(dp);
1286 rc = seq_open(file, &lprocfs_stats_seq_sops);
1291 seq = file->private_data;
1292 seq->private = dp->data;
1296 struct file_operations lprocfs_stats_seq_fops = {
1297 .owner = THIS_MODULE,
1298 .open = lprocfs_stats_seq_open,
1300 .write = lprocfs_stats_seq_write,
1301 .llseek = seq_lseek,
1302 .release = lprocfs_seq_release,
1305 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1306 struct lprocfs_stats *stats)
1308 struct proc_dir_entry *entry;
1309 LASSERT(root != NULL);
1311 entry = create_proc_entry(name, 0644, root);
1314 entry->proc_fops = &lprocfs_stats_seq_fops;
1315 entry->data = stats;
1319 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1320 unsigned conf, const char *name, const char *units)
1322 struct lprocfs_counter *c;
1324 unsigned int num_cpu;
1326 LASSERT(stats != NULL);
1328 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1330 for (i = 0; i < num_cpu; i++) {
1331 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1332 c->lc_config = conf;
1335 c->lc_min = LC_MIN_INIT;
1338 c->lc_units = units;
1341 lprocfs_stats_unlock(stats);
1343 EXPORT_SYMBOL(lprocfs_counter_init);
1345 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1347 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1348 LASSERT(coffset < stats->ls_num); \
1349 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1352 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1354 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1355 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1356 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1357 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1358 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1359 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1360 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1361 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1362 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1363 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1364 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1365 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1366 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1367 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1368 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1369 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1370 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1371 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1372 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1373 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1374 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1375 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1376 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1377 LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd);
1378 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1379 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1380 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1381 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1382 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1383 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1384 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1385 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1386 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1387 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1388 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1389 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1390 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1391 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1392 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1393 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1394 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1395 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1396 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1397 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1398 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1399 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1400 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1401 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1402 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1403 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1404 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1405 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1406 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1407 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1408 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1409 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1410 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1411 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1412 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1413 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1414 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1415 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1416 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1417 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1418 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1419 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1420 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1421 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1424 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1426 struct lprocfs_stats *stats;
1427 unsigned int num_stats;
1430 LASSERT(obd->obd_stats == NULL);
1431 LASSERT(obd->obd_proc_entry != NULL);
1432 LASSERT(obd->obd_cntr_base == 0);
1434 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1435 num_private_stats - 1 /* o_owner */;
1436 stats = lprocfs_alloc_stats(num_stats, 0);
1440 lprocfs_init_ops_stats(num_private_stats, stats);
1442 for (i = num_private_stats; i < num_stats; i++) {
1443 /* If this LBUGs, it is likely that an obd
1444 * operation was added to struct obd_ops in
1445 * <obd.h>, and that the corresponding line item
1446 * LPROCFS_OBD_OP_INIT(.., .., opname)
1447 * is missing from the list above. */
1448 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1449 "Missing obd_stat initializer obd_op "
1450 "operation at offset %d.\n", i - num_private_stats);
1452 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1454 lprocfs_free_stats(&stats);
1456 obd->obd_stats = stats;
1457 obd->obd_cntr_base = num_private_stats;
1462 void lprocfs_free_obd_stats(struct obd_device *obd)
1465 lprocfs_free_stats(&obd->obd_stats);
1468 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1470 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1471 LASSERT(coffset < stats->ls_num); \
1472 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1475 int lprocfs_alloc_md_stats(struct obd_device *obd,
1476 unsigned num_private_stats)
1478 struct lprocfs_stats *stats;
1479 unsigned int num_stats;
1482 LASSERT(obd->md_stats == NULL);
1483 LASSERT(obd->obd_proc_entry != NULL);
1484 LASSERT(obd->md_cntr_base == 0);
1486 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1488 stats = lprocfs_alloc_stats(num_stats, 0);
1492 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1493 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1494 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1495 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1496 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1497 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1498 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1499 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1500 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1501 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1502 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1503 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1504 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1505 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1506 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1507 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1508 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1509 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1510 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1511 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1512 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1513 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1514 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1515 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1516 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1517 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1518 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1519 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1520 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1521 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1522 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1524 for (i = num_private_stats; i < num_stats; i++) {
1525 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1526 CERROR("Missing md_stat initializer md_op "
1527 "operation at offset %d. Aborting.\n",
1528 i - num_private_stats);
1532 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1534 lprocfs_free_stats(&stats);
1536 obd->md_stats = stats;
1537 obd->md_cntr_base = num_private_stats;
1542 void lprocfs_free_md_stats(struct obd_device *obd)
1544 struct lprocfs_stats *stats = obd->md_stats;
1546 if (stats != NULL) {
1547 obd->md_stats = NULL;
1548 obd->md_cntr_base = 0;
1549 lprocfs_free_stats(&stats);
1553 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1555 lprocfs_counter_init(ldlm_stats,
1556 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1557 0, "ldlm_enqueue", "reqs");
1558 lprocfs_counter_init(ldlm_stats,
1559 LDLM_CONVERT - LDLM_FIRST_OPC,
1560 0, "ldlm_convert", "reqs");
1561 lprocfs_counter_init(ldlm_stats,
1562 LDLM_CANCEL - LDLM_FIRST_OPC,
1563 0, "ldlm_cancel", "reqs");
1564 lprocfs_counter_init(ldlm_stats,
1565 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1566 0, "ldlm_bl_callback", "reqs");
1567 lprocfs_counter_init(ldlm_stats,
1568 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1569 0, "ldlm_cp_callback", "reqs");
1570 lprocfs_counter_init(ldlm_stats,
1571 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1572 0, "ldlm_gl_callback", "reqs");
1575 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1576 int *eof, void *data)
1578 struct obd_export *exp = data;
1579 LASSERT(exp != NULL);
1581 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1584 struct exp_uuid_cb_data {
1592 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1593 int count, int *eof, int *len)
1595 cb_data->page = page;
1596 cb_data->count = count;
1601 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1603 struct obd_export *exp = (struct obd_export *)obj;
1604 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1606 if (exp->exp_nid_stats)
1607 *data->len += snprintf((data->page + *data->len),
1608 data->count, "%s\n",
1609 obd_uuid2str(&exp->exp_client_uuid));
1612 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1613 int *eof, void *data)
1615 struct nid_stat *stats = (struct nid_stat *)data;
1616 struct exp_uuid_cb_data cb_data;
1617 struct obd_device *obd = stats->nid_obd;
1622 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1623 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1624 lprocfs_exp_print_uuid, &cb_data);
1625 return (*cb_data.len);
1628 void lprocfs_exp_print_hash(void *obj, void *cb_data)
1630 struct exp_uuid_cb_data *data = cb_data;
1631 struct obd_export *exp = obj;
1634 lh = exp->exp_lock_hash;
1637 *data->len += lustre_hash_debug_header(data->page,
1640 *data->len += lustre_hash_debug_str(lh, data->page + *data->len,
1645 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1646 int *eof, void *data)
1648 struct nid_stat *stats = (struct nid_stat *)data;
1649 struct exp_uuid_cb_data cb_data;
1650 struct obd_device *obd = stats->nid_obd;
1655 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1657 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1658 lprocfs_exp_print_hash, &cb_data);
1659 return (*cb_data.len);
1662 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1663 int count, int *eof, void *data)
1666 return snprintf(page, count, "%s\n",
1667 "Write into this file to clear all nid stats and "
1668 "stale nid entries");
1670 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1672 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1674 struct nid_stat *stat = obj;
1677 /* object has only hash + iterate_all references.
1678 * add/delete blocked by hash bucket lock */
1679 CDEBUG(D_INFO,"refcnt %d\n", stat->nid_exp_ref_count);
1680 if (stat->nid_exp_ref_count == 2) {
1681 hlist_del_init(&stat->nid_hash);
1682 stat->nid_exp_ref_count--;
1683 spin_lock(&stat->nid_obd->obd_nid_lock);
1684 list_move(&stat->nid_list, data);
1685 spin_unlock(&stat->nid_obd->obd_nid_lock);
1689 /* we has reference to object - only clear data*/
1690 if (stat->nid_stats)
1691 lprocfs_clear_stats(stat->nid_stats);
1693 if (stat->nid_brw_stats) {
1694 for (i = 0; i < BRW_LAST; i++)
1695 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1701 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1702 unsigned long count, void *data)
1704 struct obd_device *obd = (struct obd_device *)data;
1705 struct nid_stat *client_stat;
1706 CFS_LIST_HEAD(free_list);
1708 lustre_hash_for_each(obd->obd_nid_stats_hash,
1709 lprocfs_nid_stats_clear_write_cb, &free_list);
1711 while (!list_empty(&free_list)) {
1712 client_stat = list_entry(free_list.next, struct nid_stat,
1714 list_del_init(&client_stat->nid_list);
1715 lprocfs_free_client_stats(client_stat);
1720 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1722 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1724 struct nid_stat *new_stat, *old_stat;
1725 struct nid_stat_uuid *new_ns_uuid;
1726 struct obd_device *obd = NULL;
1727 cfs_proc_dir_entry_t *entry;
1733 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1734 !exp->exp_obd->obd_nid_stats_hash)
1737 /* not test against zero because eric say:
1738 * You may only test nid against another nid, or LNET_NID_ANY.
1739 * Anything else is nonsense.*/
1740 if (!nid || *nid == LNET_NID_ANY)
1745 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1747 OBD_ALLOC_PTR(new_stat);
1748 if (new_stat == NULL)
1751 OBD_ALLOC_PTR(new_ns_uuid);
1752 if (new_ns_uuid == NULL) {
1753 OBD_FREE_PTR(new_stat);
1756 CFS_INIT_LIST_HEAD(&new_ns_uuid->ns_uuid_list);
1757 strncpy(new_ns_uuid->ns_uuid.uuid, exp->exp_client_uuid.uuid,
1758 sizeof(struct obd_uuid));
1760 CFS_INIT_LIST_HEAD(&new_stat->nid_uuid_list);
1761 new_stat->nid = *nid;
1762 new_stat->nid_obd = exp->exp_obd;
1763 new_stat->nid_exp_ref_count = 1; /* live in hash after destroy export */
1765 old_stat = lustre_hash_findadd_unique(obd->obd_nid_stats_hash,
1766 nid, &new_stat->nid_hash);
1767 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1768 old_stat, libcfs_nid2str(*nid), new_stat->nid_exp_ref_count);
1770 /* Return -EALREADY here so that we know that the /proc
1771 * entry already has been created */
1772 if (old_stat != new_stat) {
1773 struct nid_stat_uuid *tmp_uuid;
1776 exp->exp_nid_stats = old_stat;
1777 /* We need to decrement the refcount if the uuid was
1778 * already in our list */
1779 spin_lock(&obd->obd_nid_lock);
1780 list_for_each_entry(tmp_uuid, &old_stat->nid_uuid_list,
1782 if (tmp_uuid && obd_uuid_equals(&tmp_uuid->ns_uuid,
1783 &exp->exp_client_uuid)){
1785 --old_stat->nid_exp_ref_count;
1791 list_add(&new_ns_uuid->ns_uuid_list,
1792 &old_stat->nid_uuid_list);
1794 OBD_FREE_PTR(new_ns_uuid);
1796 spin_unlock(&obd->obd_nid_lock);
1798 GOTO(destroy_new, rc = -EALREADY);
1800 /* not found - create */
1801 new_stat->nid_proc = lprocfs_register(libcfs_nid2str(*nid),
1802 obd->obd_proc_exports_entry,
1804 if (new_stat->nid_proc == NULL) {
1805 CERROR("Error making export directory for nid %s\n",
1806 libcfs_nid2str(*nid));
1807 GOTO(destroy_new_ns, rc = -ENOMEM);
1810 /* Add in uuid to our nid_stats list */
1811 spin_lock(&obd->obd_nid_lock);
1812 list_add(&new_ns_uuid->ns_uuid_list, &new_stat->nid_uuid_list);
1813 spin_unlock(&obd->obd_nid_lock);
1815 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1816 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1817 if (IS_ERR(entry)) {
1818 CWARN("Error adding the NID stats file\n");
1819 rc = PTR_ERR(entry);
1820 GOTO(destroy_new_ns, rc);
1823 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1824 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1825 if (IS_ERR(entry)) {
1826 CWARN("Error adding the hash file\n");
1827 rc = PTR_ERR(entry);
1828 GOTO(destroy_new_ns, rc);
1831 exp->exp_nid_stats = new_stat;
1833 /* protect competitive add to list, not need locking on destroy */
1834 spin_lock(&obd->obd_nid_lock);
1835 list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1836 spin_unlock(&obd->obd_nid_lock);
1841 if (new_stat->nid_proc != NULL)
1842 lprocfs_remove(&new_stat->nid_proc);
1843 lustre_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1844 OBD_FREE_PTR(new_ns_uuid);
1847 OBD_FREE_PTR(new_stat);
1851 int lprocfs_exp_cleanup(struct obd_export *exp)
1853 struct nid_stat *stat = exp->exp_nid_stats;
1854 struct nid_stat_uuid *cursor, *tmp;
1857 if(!stat || !exp->exp_obd)
1860 spin_lock(&exp->exp_obd->obd_nid_lock);
1861 list_for_each_entry_safe(cursor, tmp,
1862 &stat->nid_uuid_list,
1864 if (cursor && obd_uuid_equals(&cursor->ns_uuid,
1865 &exp->exp_client_uuid)) {
1867 list_del(&cursor->ns_uuid_list);
1868 OBD_FREE_PTR(cursor);
1869 --stat->nid_exp_ref_count;
1870 CDEBUG(D_INFO, "Put stat %p - %d\n", stat,
1871 stat->nid_exp_ref_count);
1875 spin_unlock(&exp->exp_obd->obd_nid_lock);
1877 CERROR("obd_export's client uuid %s are not found in its "
1878 "nid_stats list\n", exp->exp_client_uuid.uuid);
1880 exp->exp_nid_stats = NULL;
1881 lprocfs_free_md_stats(exp->exp_obd);
1886 int lprocfs_write_helper(const char *buffer, unsigned long count,
1889 return lprocfs_write_frac_helper(buffer, count, val, 1);
1892 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1895 char kernbuf[20], *end, *pbuf;
1897 if (count > (sizeof(kernbuf) - 1))
1900 if (copy_from_user(kernbuf, buffer, count))
1903 kernbuf[count] = '\0';
1910 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1914 if (end != NULL && *end == '.') {
1915 int temp_val, pow = 1;
1919 if (strlen(pbuf) > 5)
1920 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1922 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1925 for (i = 0; i < (end - pbuf); i++)
1928 *val += temp_val / pow;
1934 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
1937 long decimal_val, frac_val;
1943 decimal_val = val / mult;
1944 prtn = snprintf(buffer, count, "%ld", decimal_val);
1945 frac_val = val % mult;
1947 if (prtn < (count - 4) && frac_val > 0) {
1949 int i, temp_mult = 1, frac_bits = 0;
1951 temp_frac = frac_val * 10;
1952 buffer[prtn++] = '.';
1953 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
1954 /* only reserved 2 bits fraction */
1955 buffer[prtn++] ='0';
1960 * Need to think these cases :
1961 * 1. #echo x.00 > /proc/xxx output result : x
1962 * 2. #echo x.0x > /proc/xxx output result : x.0x
1963 * 3. #echo x.x0 > /proc/xxx output result : x.x
1964 * 4. #echo x.xx > /proc/xxx output result : x.xx
1965 * Only reserved 2 bits fraction.
1967 for (i = 0; i < (5 - prtn); i++)
1970 frac_bits = min((int)count - prtn, 3 - frac_bits);
1971 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
1972 frac_val * temp_mult / mult);
1975 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1977 if (buffer[prtn] == '.') {
1984 buffer[prtn++] ='\n';
1988 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1990 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1993 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1994 __u64 *val, int mult)
1996 char kernbuf[22], *end, *pbuf;
1997 __u64 whole, frac = 0, units;
1998 unsigned frac_d = 1;
2000 if (count > (sizeof(kernbuf) - 1))
2003 if (copy_from_user(kernbuf, buffer, count))
2006 kernbuf[count] = '\0';
2013 whole = simple_strtoull(pbuf, &end, 10);
2017 if (end != NULL && *end == '.') {
2021 /* need to limit frac_d to a __u32 */
2022 if (strlen(pbuf) > 10)
2025 frac = simple_strtoull(pbuf, &end, 10);
2026 /* count decimal places */
2027 for (i = 0; i < (end - pbuf); i++)
2044 /* Specified units override the multiplier */
2046 mult = mult < 0 ? -units : units;
2049 do_div(frac, frac_d);
2050 *val = whole * mult + frac;
2054 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2055 struct file_operations *seq_fops, void *data)
2057 struct proc_dir_entry *entry;
2060 entry = create_proc_entry(name, mode, parent);
2063 entry->proc_fops = seq_fops;
2068 EXPORT_SYMBOL(lprocfs_seq_create);
2070 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2072 struct file_operations *seq_fops,
2075 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2076 mode, seq_fops, data));
2078 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2080 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2082 if (value >= OBD_HIST_MAX)
2083 value = OBD_HIST_MAX - 1;
2085 spin_lock(&oh->oh_lock);
2086 oh->oh_buckets[value]++;
2087 spin_unlock(&oh->oh_lock);
2089 EXPORT_SYMBOL(lprocfs_oh_tally);
2091 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2095 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2098 lprocfs_oh_tally(oh, val);
2100 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2102 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2104 unsigned long ret = 0;
2107 for (i = 0; i < OBD_HIST_MAX; i++)
2108 ret += oh->oh_buckets[i];
2111 EXPORT_SYMBOL(lprocfs_oh_sum);
2113 void lprocfs_oh_clear(struct obd_histogram *oh)
2115 spin_lock(&oh->oh_lock);
2116 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2117 spin_unlock(&oh->oh_lock);
2119 EXPORT_SYMBOL(lprocfs_oh_clear);
2121 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2122 int count, int *eof, void *data)
2124 struct obd_device *obd = data;
2130 c += lustre_hash_debug_header(page, count);
2131 c += lustre_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2132 c += lustre_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2133 c += lustre_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2137 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2139 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2140 int count, int *eof, void *data)
2142 struct obd_device *obd = data;
2145 LASSERT(obd != NULL);
2146 LASSERT(count >= 0);
2148 /* Set start of user data returned to
2149 page + off since the user may have
2150 requested to read much smaller than
2151 what we need to read */
2152 *start = page + off;
2154 /* We know we are allocated a page here.
2155 Also we know that this function will
2156 not need to write more than a page
2157 so we can truncate at CFS_PAGE_SIZE. */
2158 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2160 /* Initialize the page */
2161 memset(page, 0, size);
2163 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2165 if (obd->obd_max_recoverable_clients == 0) {
2166 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2172 /* sampled unlocked, but really... */
2173 if (obd->obd_recovering == 0) {
2174 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2176 if (lprocfs_obd_snprintf(&page, size, &len,
2177 "recovery_start: %lu\n",
2178 obd->obd_recovery_start) <= 0)
2180 if (lprocfs_obd_snprintf(&page, size, &len,
2181 "recovery_duration: %lu\n",
2182 obd->obd_recovery_end -
2183 obd->obd_recovery_start) <= 0)
2185 /* Number of clients that have completed recovery */
2186 if (lprocfs_obd_snprintf(&page, size, &len,
2187 "completed_clients: %d/%d\n",
2188 obd->obd_max_recoverable_clients -
2189 obd->obd_recoverable_clients,
2190 obd->obd_max_recoverable_clients) <= 0)
2192 if (lprocfs_obd_snprintf(&page, size, &len,
2193 "replayed_requests: %d\n",
2194 obd->obd_replayed_requests) <= 0)
2196 if (lprocfs_obd_snprintf(&page, size, &len,
2197 "last_transno: "LPD64"\n",
2198 obd->obd_next_recovery_transno - 1)<=0)
2203 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2205 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2206 obd->obd_recovery_start) <= 0)
2208 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2209 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2210 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2212 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2213 obd->obd_connected_clients,
2214 obd->obd_max_recoverable_clients) <= 0)
2216 /* Number of clients that have completed recovery */
2217 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d/%d\n",
2218 obd->obd_max_recoverable_clients -
2219 obd->obd_recoverable_clients,
2220 obd->obd_max_recoverable_clients) <= 0)
2222 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d/??\n",
2223 obd->obd_replayed_requests) <= 0)
2225 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2226 obd->obd_requests_queued_for_recovery) <= 0)
2229 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2230 obd->obd_next_recovery_transno) <= 0)
2236 return min(count, len - (int)off);
2238 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2240 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
2241 int count, int *eof, void *data)
2243 struct obd_device *obd = data;
2244 LASSERT(obd != NULL);
2246 return snprintf(page, count, "%lu\n", obd->obd_recovery_max_time);
2248 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
2250 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
2251 unsigned long count, void *data)
2253 struct obd_device *obd = data;
2255 LASSERT(obd != NULL);
2257 rc = lprocfs_write_helper(buffer, count, &val);
2261 obd->obd_recovery_max_time = val;
2264 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
2267 /**** Changelogs *****/
2268 #define D_CHANGELOG 0
2270 DECLARE_CHANGELOG_NAMES;
2272 /* How many records per seq_show. Too small, we spawn llog_process threads
2273 too often; too large, we run out of buffer space */
2274 #define CHANGELOG_CHUNK_SIZE 100
2276 static int changelog_show_cb(struct llog_handle *llh, struct llog_rec_hdr *hdr,
2279 struct seq_file *seq = (struct seq_file *)data;
2280 struct changelog_seq_iter *csi = seq->private;
2281 struct llog_changelog_rec *rec = (struct llog_changelog_rec *)hdr;
2285 if ((rec->cr_hdr.lrh_type != CHANGELOG_REC) ||
2286 (rec->cr_type >= CL_LAST)) {
2287 CERROR("Not a changelog rec %d/%d\n", rec->cr_hdr.lrh_type,
2292 CDEBUG(D_CHANGELOG, "rec="LPU64" start="LPU64" cat=%d:%d start=%d:%d\n",
2293 rec->cr_index, csi->csi_startrec,
2294 llh->lgh_hdr->llh_cat_idx, llh->lgh_cur_idx,
2295 csi->csi_startcat, csi->csi_startidx);
2297 if (rec->cr_index < csi->csi_startrec)
2298 /* Skip entries earlier than what we are interested in */
2300 if (rec->cr_index == csi->csi_startrec) {
2301 /* Remember where we started, since seq_read will re-read
2302 * the data when it reallocs space. Sigh, if only there was
2303 * a way to tell seq_file how big the buf should be in the
2306 csi->csi_startcat = llh->lgh_hdr->llh_cat_idx;
2307 csi->csi_startidx = rec->cr_hdr.lrh_index - 1;
2309 if (csi->csi_wrote > CHANGELOG_CHUNK_SIZE) {
2310 /* Stop at some point with a reasonable seq_file buffer size.
2311 * Start from here the next time.
2313 csi->csi_endrec = rec->cr_index - 1;
2314 csi->csi_startcat = llh->lgh_hdr->llh_cat_idx;
2315 csi->csi_startidx = rec->cr_hdr.lrh_index - 1;
2317 RETURN(LLOG_PROC_BREAK);
2320 rc = seq_printf(seq, LPU64" %02d%-5s "LPU64" 0x%x t="DFID,
2321 rec->cr_index, rec->cr_type,
2322 changelog_str[rec->cr_type], rec->cr_time,
2323 rec->cr_flags & CLF_FLAGMASK, PFID(&rec->cr_tfid));
2325 if (rec->cr_namelen)
2326 /* namespace rec includes parent and filename */
2327 rc += seq_printf(seq, " p="DFID" %.*s\n", PFID(&rec->cr_pfid),
2328 rec->cr_namelen, rec->cr_name);
2330 rc += seq_puts(seq, "\n");
2333 /* Ran out of room in the seq buffer. seq_read will dump
2334 * the whole buffer and re-seq_start with a larger one;
2335 * no point in continuing the llog_process */
2336 CDEBUG(D_CHANGELOG, "rec="LPU64" overflow "LPU64"<-"LPU64"\n",
2337 rec->cr_index, csi->csi_startrec, csi->csi_endrec);
2338 csi->csi_endrec = csi->csi_startrec - 1;
2340 RETURN(LLOG_PROC_BREAK);
2344 csi->csi_endrec = rec->cr_index;
2349 static int changelog_seq_show(struct seq_file *seq, void *v)
2351 struct changelog_seq_iter *csi = seq->private;
2355 if (csi->csi_fill) {
2356 /* seq_read wants more data to fill his buffer. But we already
2357 filled the buf as much as we cared to; force seq_read to
2358 accept that by padding with 0's */
2359 while (seq_putc(seq, 0) == 0);
2363 /* Since we have to restart the llog_cat_process for each chunk of the
2364 seq_ functions, start from where we left off. */
2365 rc = llog_cat_process(csi->csi_llh, changelog_show_cb, seq,
2366 csi->csi_startcat, csi->csi_startidx);
2368 CDEBUG(D_CHANGELOG,"seq_show "LPU64"-"LPU64" cat=%d:%d wrote=%d rc=%d\n",
2369 csi->csi_startrec, csi->csi_endrec, csi->csi_startcat,
2370 csi->csi_startidx, csi->csi_wrote, rc);
2374 if (rc == LLOG_PROC_BREAK)
2375 /* more records left, but seq_show must return 0 */
2380 static void *changelog_seq_start(struct seq_file *seq, loff_t *pos)
2382 struct changelog_seq_iter *csi = seq->private;
2385 CDEBUG(D_CHANGELOG, "start "LPU64"-"LPU64" pos="LPU64"\n",
2386 csi->csi_startrec, csi->csi_endrec, *pos);
2391 /* no more records, seq_read should return 0 if buffer
2395 if (*pos > csi->csi_pos) {
2396 /* The seq_read implementation sucks. It may call start
2397 multiple times, using pos to indicate advances, if any,
2398 by arbitrarily increasing it by 1. So ignore the actual
2399 value of pos, and just register any increase as
2400 "seq_read wants the next values". */
2401 csi->csi_startrec = csi->csi_endrec + 1;
2402 csi->csi_pos = *pos;
2404 /* else use old startrec/startidx */
2409 static void changelog_seq_stop(struct seq_file *seq, void *v)
2411 struct changelog_seq_iter *csi = seq->private;
2413 CDEBUG(D_CHANGELOG, "stop "LPU64"-"LPU64"\n",
2414 csi->csi_startrec, csi->csi_endrec);
2417 static void *changelog_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2419 struct changelog_seq_iter *csi = seq->private;
2421 CDEBUG(D_CHANGELOG, "next "LPU64"-"LPU64" pos="LPU64"\n",
2422 csi->csi_startrec, csi->csi_endrec, *pos);
2429 static struct seq_operations changelog_sops = {
2430 .start = changelog_seq_start,
2431 .stop = changelog_seq_stop,
2432 .next = changelog_seq_next,
2433 .show = changelog_seq_show,
2436 int changelog_seq_open(struct inode *inode, struct file *file,
2437 struct changelog_seq_iter **csih)
2439 struct changelog_seq_iter *csi;
2440 struct proc_dir_entry *dp = PDE(inode);
2441 struct seq_file *seq;
2444 LPROCFS_ENTRY_AND_CHECK(dp);
2446 rc = seq_open(file, &changelog_sops);
2454 lprocfs_seq_release(inode, file);
2458 csi->csi_dev = dp->data;
2459 seq = file->private_data;
2465 EXPORT_SYMBOL(changelog_seq_open);
2467 int changelog_seq_release(struct inode *inode, struct file *file)
2469 struct seq_file *seq = file->private_data;
2470 struct changelog_seq_iter *csi = seq->private;
2475 return lprocfs_seq_release(inode, file);
2477 EXPORT_SYMBOL(changelog_seq_release);
2479 #ifndef SEEK_CUR /* SLES10 needs this */
2484 loff_t changelog_seq_lseek(struct file *file, loff_t offset, int origin)
2486 struct seq_file *seq = (struct seq_file *)file->private_data;
2487 struct changelog_seq_iter *csi = seq->private;
2489 CDEBUG(D_CHANGELOG,"seek "LPU64"-"LPU64" off="LPU64":%d fpos="LPU64"\n",
2490 csi->csi_startrec, csi->csi_endrec, offset, origin, file->f_pos);
2496 offset += csi->csi_endrec;
2499 /* we don't know the last rec */
2510 csi->csi_startrec = offset;
2511 csi->csi_endrec = offset ? offset - 1 : 0;
2513 /* drop whatever is left in sucky seq_read's buffer */
2518 file->f_pos = csi->csi_startrec;
2519 return csi->csi_startrec;
2521 EXPORT_SYMBOL(changelog_seq_lseek);
2523 EXPORT_SYMBOL(lprocfs_register);
2524 EXPORT_SYMBOL(lprocfs_srch);
2525 EXPORT_SYMBOL(lprocfs_remove);
2526 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2527 EXPORT_SYMBOL(lprocfs_add_vars);
2528 EXPORT_SYMBOL(lprocfs_obd_setup);
2529 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2530 EXPORT_SYMBOL(lprocfs_add_simple);
2531 EXPORT_SYMBOL(lprocfs_add_symlink);
2532 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2533 EXPORT_SYMBOL(lprocfs_alloc_stats);
2534 EXPORT_SYMBOL(lprocfs_free_stats);
2535 EXPORT_SYMBOL(lprocfs_clear_stats);
2536 EXPORT_SYMBOL(lprocfs_register_stats);
2537 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2538 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2539 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2540 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2541 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2542 EXPORT_SYMBOL(lprocfs_exp_setup);
2543 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2545 EXPORT_SYMBOL(lprocfs_rd_u64);
2546 EXPORT_SYMBOL(lprocfs_rd_atomic);
2547 EXPORT_SYMBOL(lprocfs_wr_atomic);
2548 EXPORT_SYMBOL(lprocfs_rd_uint);
2549 EXPORT_SYMBOL(lprocfs_wr_uint);
2550 EXPORT_SYMBOL(lprocfs_rd_uuid);
2551 EXPORT_SYMBOL(lprocfs_rd_name);
2552 EXPORT_SYMBOL(lprocfs_rd_fstype);
2553 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2554 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2555 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2556 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2557 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2558 EXPORT_SYMBOL(lprocfs_rd_import);
2559 EXPORT_SYMBOL(lprocfs_rd_state);
2560 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2561 EXPORT_SYMBOL(lprocfs_rd_blksize);
2562 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2563 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2564 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2565 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2566 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2568 EXPORT_SYMBOL(lprocfs_write_helper);
2569 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2570 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2571 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2572 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2573 EXPORT_SYMBOL(lprocfs_stats_collect);