1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2002, 2003 Cluster File Systems, Inc.
5 * Author: Hariharan Thantry <thantry@users.sourceforge.net>
7 * This file is part of the Lustre file system, http://www.lustre.org
8 * Lustre is a trademark of Cluster File Systems, Inc.
10 * You may have signed or agreed to another license before downloading
11 * this software. If so, you are bound by the terms and conditions
12 * of that agreement, and the following does not apply to you. See the
13 * LICENSE file included with this distribution for more information.
15 * If you did not agree to a different license, then this copy of Lustre
16 * is open source software; you can redistribute it and/or modify it
17 * under the terms of version 2 of the GNU General Public License as
18 * published by the Free Software Foundation.
20 * In either case, Lustre is distributed in the hope that it will be
21 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
22 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * license text for more details.
27 # define EXPORT_SYMTAB
29 #define DEBUG_SUBSYSTEM S_CLASS
32 # include <liblustre.h>
35 #include <obd_class.h>
36 #include <lprocfs_status.h>
37 #include <lustre_fsfilt.h>
41 #define MAX_STRING_SIZE 128
43 /* for bug 10866, global variable */
44 DECLARE_RWSEM(_lprocfs_lock);
45 EXPORT_SYMBOL(_lprocfs_lock);
47 int lprocfs_seq_release(struct inode *inode, struct file *file)
50 return seq_release(inode, file);
52 EXPORT_SYMBOL(lprocfs_seq_release);
54 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
57 struct proc_dir_entry *temp;
64 while (temp != NULL) {
65 if (strcmp(temp->name, name) == 0) {
76 /* lprocfs API calls */
78 /* Function that emulates snprintf but also has the side effect of advancing
79 the page pointer for the next write into the buffer, incrementing the total
80 length written to the buffer, and decrementing the size left in the
82 static int lprocfs_obd_snprintf(char **page, int end, int *len,
83 const char *format, ...)
91 va_start(list, format);
92 n = vsnprintf(*page, end - *len, format, list);
95 *page += n; *len += n;
99 int lprocfs_add_simple(struct proc_dir_entry *root, char *name,
100 read_proc_t *read_proc, write_proc_t *write_proc,
103 struct proc_dir_entry *proc;
106 if (root == NULL || name == NULL)
112 proc = create_proc_entry(name, mode, root);
114 CERROR("LprocFS: No memory to create /proc entry %s", name);
117 proc->read_proc = read_proc;
118 proc->write_proc = write_proc;
124 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf, size_t size, loff_t *ppos)
126 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
127 char *page, *start = NULL;
128 int rc = 0, eof = 1, count;
130 if (*ppos >= PAGE_SIZE)
133 page = (char *)__get_free_page(GFP_KERNEL);
138 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
139 if (!dp->deleted && dp->read_proc)
140 rc = dp->read_proc(page, &start, *ppos, PAGE_SIZE,
146 /* for lustre proc read, the read count must be less than PAGE_SIZE */
155 start = page + *ppos;
156 } else if (start < page) {
160 count = (rc < size) ? rc : size;
161 if (copy_to_user(buf, start, count)) {
168 free_page((unsigned long)page);
172 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf, size_t size, loff_t *ppos)
174 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
178 if (!dp->deleted && dp->write_proc)
179 rc = dp->write_proc(f, buf, size, dp->data);
184 static struct file_operations lprocfs_generic_fops = {
185 .owner = THIS_MODULE,
186 .read = lprocfs_fops_read,
187 .write = lprocfs_fops_write,
190 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
192 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
193 struct obd_device *obd = dp->data;
195 atomic_inc(&obd->obd_evict_inprogress);
200 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
202 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
203 struct obd_device *obd = dp->data;
205 atomic_dec(&obd->obd_evict_inprogress);
206 wake_up(&obd->obd_evict_inprogress_waitq);
211 struct file_operations lprocfs_evict_client_fops = {
212 .owner = THIS_MODULE,
213 .read = lprocfs_fops_read,
214 .write = lprocfs_fops_write,
215 .open = lprocfs_evict_client_open,
216 .release = lprocfs_evict_client_release,
218 EXPORT_SYMBOL(lprocfs_evict_client_fops);
220 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
223 if (root == NULL || list == NULL)
226 while (list->name != NULL) {
227 struct proc_dir_entry *cur_root, *proc;
228 char *pathcopy, *cur, *next, pathbuf[64];
229 int pathsize = strlen(list->name) + 1;
234 /* need copy of path for strsep */
235 if (strlen(list->name) > sizeof(pathbuf) - 1) {
236 OBD_ALLOC(pathcopy, pathsize);
237 if (pathcopy == NULL)
244 strcpy(pathcopy, list->name);
246 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
247 if (*cur =='\0') /* skip double/trailing "/" */
250 proc = lprocfs_srch(cur_root, cur);
251 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
252 cur_root->name, cur, next,
253 (proc ? "exists" : "new"));
255 cur_root = (proc ? proc :
256 proc_mkdir(cur, cur_root));
257 } else if (proc == NULL) {
261 if (list->write_fptr)
263 proc = create_proc_entry(cur, mode, cur_root);
267 if (pathcopy != pathbuf)
268 OBD_FREE(pathcopy, pathsize);
270 if (cur_root == NULL || proc == NULL) {
271 CERROR("LprocFS: No memory to create /proc entry %s",
277 proc->proc_fops = list->fops;
279 proc->proc_fops = &lprocfs_generic_fops;
280 proc->read_proc = list->read_fptr;
281 proc->write_proc = list->write_fptr;
282 proc->data = (list->data ? list->data : data);
288 void lprocfs_remove(struct proc_dir_entry **rooth)
290 struct proc_dir_entry *root = *rooth;
291 struct proc_dir_entry *temp = root;
292 struct proc_dir_entry *rm_entry;
293 struct proc_dir_entry *parent;
299 parent = root->parent;
300 LASSERT(parent != NULL);
301 LPROCFS_ENTRY(); /* search vs remove race */
304 while (temp->subdir != NULL)
310 /* Memory corruption once caused this to fail, and
311 without this LASSERT we would loop here forever. */
312 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
313 "0x%p %s/%s len %d\n", rm_entry, temp->name,
314 rm_entry->name, (int)strlen(rm_entry->name));
316 /* Now, the rm_entry->deleted flags is protected
317 * by _lprocfs_lock. */
318 rm_entry->data = NULL;
319 remove_proc_entry(rm_entry->name, temp);
326 struct proc_dir_entry *lprocfs_register(const char *name,
327 struct proc_dir_entry *parent,
328 struct lprocfs_vars *list, void *data)
330 struct proc_dir_entry *newchild;
332 newchild = lprocfs_srch(parent, name);
333 if (newchild != NULL) {
334 CERROR(" Lproc: Attempting to register %s more than once \n",
336 return ERR_PTR(-EALREADY);
339 newchild = proc_mkdir(name, parent);
340 if (newchild != NULL && list != NULL) {
341 int rc = lprocfs_add_vars(newchild, list, data);
343 lprocfs_remove(&newchild);
350 /* Generic callbacks */
351 int lprocfs_rd_uint(char *page, char **start, off_t off,
352 int count, int *eof, void *data)
354 unsigned int *temp = (unsigned int *)data;
355 return snprintf(page, count, "%u\n", *temp);
358 int lprocfs_wr_uint(struct file *file, const char *buffer,
359 unsigned long count, void *data)
362 char dummy[MAX_STRING_SIZE + 1] = { '\0' }, *end;
365 if (count >= sizeof(dummy) || count == 0)
368 if (copy_from_user(dummy, buffer, count))
371 tmp = simple_strtoul(dummy, &end, 0);
375 *p = (unsigned int)tmp;
379 int lprocfs_rd_u64(char *page, char **start, off_t off,
380 int count, int *eof, void *data)
382 LASSERT(data != NULL);
384 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
387 int lprocfs_rd_atomic(char *page, char **start, off_t off,
388 int count, int *eof, void *data)
390 atomic_t *atom = (atomic_t *)data;
391 LASSERT(atom != NULL);
393 return snprintf(page, count, "%d\n", atomic_read(atom));
396 int lprocfs_wr_atomic(struct file *file, const char *buffer,
397 unsigned long count, void *data)
399 atomic_t *atm = data;
403 rc = lprocfs_write_helper(buffer, count, &val);
410 atomic_set(atm, val);
414 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
415 int *eof, void *data)
417 struct obd_device *obd = (struct obd_device*)data;
419 LASSERT(obd != NULL);
421 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
424 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
425 int *eof, void* data)
427 struct obd_device *dev = (struct obd_device *)data;
429 LASSERT(dev != NULL);
430 LASSERT(dev->obd_name != NULL);
432 return snprintf(page, count, "%s\n", dev->obd_name);
435 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
438 struct obd_device *obd = (struct obd_device *)data;
440 LASSERT(obd != NULL);
441 LASSERT(obd->obd_fsops != NULL);
442 LASSERT(obd->obd_fsops->fs_type != NULL);
443 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
446 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
447 int *eof, void *data)
449 struct obd_statfs osfs;
450 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
454 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
459 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
460 int *eof, void *data)
462 struct obd_statfs osfs;
463 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
466 __u32 blk_size = osfs.os_bsize >> 10;
467 __u64 result = osfs.os_blocks;
469 while (blk_size >>= 1)
473 rc = snprintf(page, count, LPU64"\n", result);
478 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
479 int *eof, void *data)
481 struct obd_statfs osfs;
482 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
485 __u32 blk_size = osfs.os_bsize >> 10;
486 __u64 result = osfs.os_bfree;
488 while (blk_size >>= 1)
492 rc = snprintf(page, count, LPU64"\n", result);
497 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
498 int *eof, void *data)
500 struct obd_statfs osfs;
501 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
504 __u32 blk_size = osfs.os_bsize >> 10;
505 __u64 result = osfs.os_bavail;
507 while (blk_size >>= 1)
511 rc = snprintf(page, count, LPU64"\n", result);
516 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
517 int *eof, void *data)
519 struct obd_statfs osfs;
520 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
524 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
530 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
531 int *eof, void *data)
533 struct obd_statfs osfs;
534 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
538 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
543 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
544 int *eof, void *data)
546 struct obd_device *obd = (struct obd_device *)data;
547 struct obd_import *imp;
548 char *imp_state_name = NULL;
551 LASSERT(obd != NULL);
552 LPROCFS_CLIMP_CHECK(obd);
553 imp = obd->u.cli.cl_import;
554 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
556 rc = snprintf(page, count, "%s\t%s%s\n",
557 obd2cli_tgt(obd), imp_state_name,
558 imp->imp_deactive ? "\tDEACTIVATED" : "");
560 LPROCFS_CLIMP_EXIT(obd);
564 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
565 int *eof, void *data)
567 struct obd_device *obd = (struct obd_device*)data;
568 struct ptlrpc_connection *conn;
571 LASSERT(obd != NULL);
572 LPROCFS_CLIMP_CHECK(obd);
573 conn = obd->u.cli.cl_import->imp_connection;
574 LASSERT(conn != NULL);
576 rc = snprintf(page, count, "%s\n", conn->c_remote_uuid.uuid);
578 LPROCFS_CLIMP_EXIT(obd);
582 int lprocfs_at_hist_helper(char *page, int count, int rc,
583 struct adaptive_timeout *at)
586 for (i = 0; i < AT_BINS; i++)
587 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
588 rc += snprintf(page + rc, count - rc, "\n");
592 /* See also ptlrpc_lprocfs_rd_timeouts */
593 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
594 int *eof, void *data)
596 struct obd_device *obd = (struct obd_device *)data;
597 struct obd_import *imp;
598 unsigned int cur, worst;
603 LASSERT(obd != NULL);
604 LPROCFS_CLIMP_CHECK(obd);
605 imp = obd->u.cli.cl_import;
608 now = cfs_time_current_sec();
610 /* Some network health info for kicks */
611 s2dhms(&ts, now - imp->imp_last_reply_time);
612 rc += snprintf(page + rc, count - rc,
613 "%-10s : %ld, "DHMS_FMT" ago\n",
614 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
617 cur = at_get(&imp->imp_at.iat_net_latency);
618 worst = imp->imp_at.iat_net_latency.at_worst_ever;
619 worstt = imp->imp_at.iat_net_latency.at_worst_time;
620 s2dhms(&ts, now - worstt);
621 rc += snprintf(page + rc, count - rc,
622 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
623 "network", cur, worst, worstt, DHMS_VARS(&ts));
624 rc = lprocfs_at_hist_helper(page, count, rc,
625 &imp->imp_at.iat_net_latency);
627 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
628 if (imp->imp_at.iat_portal[i] == 0)
630 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
631 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
632 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
633 s2dhms(&ts, now - worstt);
634 rc += snprintf(page + rc, count - rc,
635 "portal %-2d : cur %3u worst %3u (at %ld, "
636 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
637 cur, worst, worstt, DHMS_VARS(&ts));
638 rc = lprocfs_at_hist_helper(page, count, rc,
639 &imp->imp_at.iat_service_estimate[i]);
642 LPROCFS_CLIMP_EXIT(obd);
646 static const char *obd_connect_names[] = {
673 "mds_mds_connection",
676 "alt_checksum_algorithm",
681 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
682 int count, int *eof, void *data)
684 struct obd_device *obd = data;
685 __u64 mask = 1, flags;
688 LPROCFS_CLIMP_CHECK(obd);
689 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
690 ret = snprintf(page, count, "flags="LPX64"\n", flags);
691 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
693 ret += snprintf(page + ret, count - ret, "%s\n",
694 obd_connect_names[i]);
696 if (flags & ~(mask - 1))
697 ret += snprintf(page + ret, count - ret,
698 "unknown flags "LPX64"\n", flags & ~(mask - 1));
700 LPROCFS_CLIMP_EXIT(obd);
703 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
705 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
706 int *eof, void *data)
708 struct obd_device *obd = (struct obd_device*)data;
710 LASSERT(obd != NULL);
712 return snprintf(page, count, "%u\n", obd->obd_num_exports);
715 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
716 int *eof, void *data)
718 struct obd_type *class = (struct obd_type*) data;
720 LASSERT(class != NULL);
722 return snprintf(page, count, "%d\n", class->typ_refcnt);
725 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
729 LASSERT(obd != NULL);
730 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
731 LASSERT(obd->obd_type->typ_procroot != NULL);
733 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
734 obd->obd_type->typ_procroot,
736 if (IS_ERR(obd->obd_proc_entry)) {
737 rc = PTR_ERR(obd->obd_proc_entry);
738 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
739 obd->obd_proc_entry = NULL;
744 int lprocfs_obd_cleanup(struct obd_device *obd)
748 if (obd->obd_proc_exports_entry) {
749 /* Should be no exports left */
750 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
751 lprocfs_remove(&obd->obd_proc_exports_entry);
753 lprocfs_remove(&obd->obd_proc_entry);
757 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
759 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
760 client_stat->nid_proc, client_stat->nid_stats,
761 client_stat->nid_brw_stats);
763 LASSERTF(client_stat->nid_exp_ref_count == 0, "count %d\n",
764 client_stat->nid_exp_ref_count);
766 hlist_del_init(&client_stat->nid_hash);
768 if (client_stat->nid_proc)
769 lprocfs_remove(&client_stat->nid_proc);
771 if (client_stat->nid_stats)
772 lprocfs_free_stats(&client_stat->nid_stats);
774 if (client_stat->nid_brw_stats)
775 OBD_FREE(client_stat->nid_brw_stats, sizeof(struct brw_stats));
777 OBD_FREE(client_stat, sizeof(*client_stat));
782 void lprocfs_free_per_client_stats(struct obd_device *obd)
784 struct nid_stat *stat;
787 /* we need extra list - because hash_exit called to early */
788 /* not need locking because all clients is died */
789 while(!list_empty(&obd->obd_nid_stats)) {
790 stat = list_entry(obd->obd_nid_stats.next,
791 struct nid_stat, nid_list);
792 list_del_init(&stat->nid_list);
793 lprocfs_free_client_stats(stat);
799 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
800 enum lprocfs_stats_flags flags)
802 struct lprocfs_stats *stats;
803 unsigned int percpusize;
805 unsigned int num_cpu;
810 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
813 num_cpu = num_possible_cpus();
815 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
819 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
820 stats->ls_flags = flags;
821 spin_lock_init(&stats->ls_lock);
822 /* Use this lock only if there are no percpu areas */
827 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
829 percpusize = L1_CACHE_ALIGN(percpusize);
831 for (i = 0; i < num_cpu; i++) {
832 OBD_ALLOC(stats->ls_percpu[i], percpusize);
833 if (stats->ls_percpu[i] == NULL) {
834 for (j = 0; j < i; j++) {
835 OBD_FREE(stats->ls_percpu[j], percpusize);
836 stats->ls_percpu[j] = NULL;
841 if (stats->ls_percpu[0] == NULL) {
842 OBD_FREE(stats, offsetof(typeof(*stats),
843 ls_percpu[num_cpu]));
851 void lprocfs_free_stats(struct lprocfs_stats **statsh)
853 struct lprocfs_stats *stats = *statsh;
854 unsigned int num_cpu;
855 unsigned int percpusize;
858 if (!stats || (stats->ls_num == 0))
861 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
864 num_cpu = num_possible_cpus();
866 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
868 percpusize = L1_CACHE_ALIGN(percpusize);
869 for (i = 0; i < num_cpu; i++)
870 OBD_FREE(stats->ls_percpu[i], percpusize);
871 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
874 void lprocfs_clear_stats(struct lprocfs_stats *stats)
876 struct lprocfs_counter *percpu_cntr;
878 unsigned int num_cpu;
880 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
882 for (i = 0; i < num_cpu; i++) {
883 for (j = 0; j < stats->ls_num; j++) {
884 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
885 atomic_inc(&percpu_cntr->lc_cntl.la_entry);
886 percpu_cntr->lc_count = 0;
887 percpu_cntr->lc_sum = 0;
888 percpu_cntr->lc_min = LC_MIN_INIT;
889 percpu_cntr->lc_max = 0;
890 percpu_cntr->lc_sumsquare = 0;
891 atomic_inc(&percpu_cntr->lc_cntl.la_exit);
895 lprocfs_stats_unlock(stats);
898 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
899 size_t len, loff_t *off)
901 struct seq_file *seq = file->private_data;
902 struct lprocfs_stats *stats = seq->private;
904 lprocfs_clear_stats(stats);
909 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
911 struct lprocfs_stats *stats = p->private;
912 /* return 1st cpu location */
913 return (*pos >= stats->ls_num) ? NULL :
914 &(stats->ls_percpu[0]->lp_cntr[*pos]);
917 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
921 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
923 struct lprocfs_stats *stats = p->private;
925 return (*pos >= stats->ls_num) ? NULL :
926 &(stats->ls_percpu[0]->lp_cntr[*pos]);
929 /* seq file export of one lprocfs counter */
930 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
932 struct lprocfs_stats *stats = p->private;
933 struct lprocfs_counter *cntr = v;
934 struct lprocfs_counter t, ret = { .lc_min = LC_MIN_INIT };
936 unsigned int num_cpu;
938 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
940 do_gettimeofday(&now);
941 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
942 "snapshot_time", now.tv_sec, now.tv_usec);
946 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
948 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
951 num_cpu = num_possible_cpus();
953 for (i = 0; i < num_cpu; i++) {
954 struct lprocfs_counter *percpu_cntr =
955 &(stats->ls_percpu[i])->lp_cntr[idx];
959 centry = atomic_read(&percpu_cntr->lc_cntl.la_entry);
960 t.lc_count = percpu_cntr->lc_count;
961 t.lc_sum = percpu_cntr->lc_sum;
962 t.lc_min = percpu_cntr->lc_min;
963 t.lc_max = percpu_cntr->lc_max;
964 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
965 } while (centry != atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
966 centry != atomic_read(&percpu_cntr->lc_cntl.la_exit));
967 ret.lc_count += t.lc_count;
968 ret.lc_sum += t.lc_sum;
969 if (t.lc_min < ret.lc_min)
970 ret.lc_min = t.lc_min;
971 if (t.lc_max > ret.lc_max)
972 ret.lc_max = t.lc_max;
973 ret.lc_sumsquare += t.lc_sumsquare;
976 if (ret.lc_count == 0)
979 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
980 ret.lc_count, cntr->lc_units);
984 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
985 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
986 ret.lc_min, ret.lc_max, ret.lc_sum);
989 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
990 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
994 rc = seq_printf(p, "\n");
996 return (rc < 0) ? rc : 0;
999 struct seq_operations lprocfs_stats_seq_sops = {
1000 start: lprocfs_stats_seq_start,
1001 stop: lprocfs_stats_seq_stop,
1002 next: lprocfs_stats_seq_next,
1003 show: lprocfs_stats_seq_show,
1006 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1008 struct proc_dir_entry *dp = PDE(inode);
1009 struct seq_file *seq;
1012 LPROCFS_ENTRY_AND_CHECK(dp);
1013 rc = seq_open(file, &lprocfs_stats_seq_sops);
1019 seq = file->private_data;
1020 seq->private = dp->data;
1024 struct file_operations lprocfs_stats_seq_fops = {
1025 .owner = THIS_MODULE,
1026 .open = lprocfs_stats_seq_open,
1028 .write = lprocfs_stats_seq_write,
1029 .llseek = seq_lseek,
1030 .release = lprocfs_seq_release,
1033 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1034 struct lprocfs_stats *stats)
1036 struct proc_dir_entry *entry;
1037 LASSERT(root != NULL);
1039 entry = create_proc_entry(name, 0644, root);
1042 entry->proc_fops = &lprocfs_stats_seq_fops;
1043 entry->data = (void *)stats;
1047 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1048 unsigned conf, const char *name, const char *units)
1050 struct lprocfs_counter *c;
1052 unsigned int num_cpu;
1054 LASSERT(stats != NULL);
1056 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1058 for (i = 0; i < num_cpu; i++) {
1059 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1060 c->lc_config = conf;
1063 c->lc_min = LC_MIN_INIT;
1066 c->lc_units = units;
1069 lprocfs_stats_unlock(stats);
1071 EXPORT_SYMBOL(lprocfs_counter_init);
1073 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1075 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1076 LASSERT(coffset < stats->ls_num); \
1077 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1080 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1082 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1083 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1084 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1085 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1086 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1087 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1088 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1089 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1090 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1091 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1092 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1093 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1094 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1095 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1096 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1097 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1098 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1099 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1100 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1101 LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd);
1102 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1103 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1104 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1105 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1106 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1107 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1108 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1109 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1110 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1111 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw_async);
1112 LPROCFS_OBD_OP_INIT(num_private_stats, stats, prep_async_page);
1113 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reget_short_lock);
1114 LPROCFS_OBD_OP_INIT(num_private_stats, stats, release_short_lock);
1115 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_async_io);
1116 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_group_io);
1117 LPROCFS_OBD_OP_INIT(num_private_stats, stats, trigger_group_io);
1118 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_async_flags);
1119 LPROCFS_OBD_OP_INIT(num_private_stats, stats, teardown_async_page);
1120 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1121 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1122 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1123 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1124 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1125 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1126 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1127 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1128 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1129 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1130 LPROCFS_OBD_OP_INIT(num_private_stats, stats, match);
1131 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1132 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1133 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1134 LPROCFS_OBD_OP_INIT(num_private_stats, stats, join_lru);
1135 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1136 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1137 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1138 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1139 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1140 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1141 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1142 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1143 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1144 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1145 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1146 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1147 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1148 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1149 LPROCFS_OBD_OP_INIT(num_private_stats, stats, register_page_removal_cb);
1150 LPROCFS_OBD_OP_INIT(num_private_stats,stats,unregister_page_removal_cb);
1151 LPROCFS_OBD_OP_INIT(num_private_stats, stats, register_lock_cancel_cb);
1152 LPROCFS_OBD_OP_INIT(num_private_stats, stats,unregister_lock_cancel_cb);
1155 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1157 struct lprocfs_stats *stats;
1158 unsigned int num_stats;
1161 LASSERT(obd->obd_stats == NULL);
1162 LASSERT(obd->obd_proc_entry != NULL);
1163 LASSERT(obd->obd_cntr_base == 0);
1165 num_stats = ((int)sizeof(*obd->obd_type->typ_ops) / sizeof(void *)) +
1166 num_private_stats - 1 /* o_owner */;
1167 stats = lprocfs_alloc_stats(num_stats, 0);
1171 lprocfs_init_ops_stats(num_private_stats, stats);
1173 for (i = num_private_stats; i < num_stats; i++) {
1174 /* If this LBUGs, it is likely that an obd
1175 * operation was added to struct obd_ops in
1176 * <obd.h>, and that the corresponding line item
1177 * LPROCFS_OBD_OP_INIT(.., .., opname)
1178 * is missing from the list above. */
1179 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1180 "Missing obd_stat initializer obd_op "
1181 "operation at offset %d.\n", i - num_private_stats);
1183 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1185 lprocfs_free_stats(&stats);
1187 obd->obd_stats = stats;
1188 obd->obd_cntr_base = num_private_stats;
1193 void lprocfs_free_obd_stats(struct obd_device *obd)
1196 lprocfs_free_stats(&obd->obd_stats);
1199 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1200 int *eof, void *data)
1202 struct obd_export *exp = (struct obd_export*)data;
1203 LASSERT(exp != NULL);
1205 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1208 struct exp_uuid_cb_data {
1215 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1217 struct obd_export *exp = (struct obd_export *)obj;
1218 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1220 if (exp->exp_nid_stats)
1221 *data->len += snprintf((data->page + *data->len),
1222 data->count, "%s\n",
1223 obd_uuid2str(&exp->exp_client_uuid));
1226 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1227 int *eof, void *data)
1229 struct nid_stat *stats = (struct nid_stat *)data;
1230 struct exp_uuid_cb_data cb_data;
1231 struct obd_device *obd = stats->nid_obd;
1236 LASSERT(obd != NULL);
1238 cb_data.page = page;
1239 cb_data.count = count;
1242 lustre_hash_bucket_iterate(obd->obd_nid_hash_body,
1243 &stats->nid, lprocfs_exp_print_uuid,
1245 return (*cb_data.len);
1248 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1249 int count, int *eof, void *data)
1252 return snprintf(page, count, "%s\n",
1253 "Write into this file to clear all nid stats and "
1254 "stale nid entries");
1256 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1258 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1260 struct nid_stat *stat = obj;
1263 /* object has only hash + iterate_all references.
1264 * add/delete blocked by hash bucket lock */
1265 CDEBUG(D_INFO,"refcnt %d\n", stat->nid_exp_ref_count);
1266 if(stat->nid_exp_ref_count == 2) {
1267 hlist_del_init(&stat->nid_hash);
1268 stat->nid_exp_ref_count--;
1269 spin_lock(&stat->nid_obd->obd_nid_lock);
1270 list_del_init(&stat->nid_list);
1271 spin_unlock(&stat->nid_obd->obd_nid_lock);
1272 list_add(&stat->nid_list, data);
1276 /* we has reference to object - only clear data*/
1277 if (stat->nid_stats)
1278 lprocfs_clear_stats(stat->nid_stats);
1280 if (stat->nid_brw_stats) {
1281 for (i = 0; i < BRW_LAST; i++)
1282 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1289 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1290 unsigned long count, void *data)
1292 struct obd_device *obd = (struct obd_device *)data;
1293 struct nid_stat *client_stat;
1294 CFS_LIST_HEAD(free_list);
1296 lustre_hash_iterate_all(obd->obd_nid_stats_hash_body,
1297 lprocfs_nid_stats_clear_write_cb, &free_list);
1299 while (!list_empty(&free_list)) {
1300 client_stat = list_entry(free_list.next, struct nid_stat, nid_list);
1301 list_del_init(&client_stat->nid_list);
1302 lprocfs_free_client_stats(client_stat);
1307 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1309 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1312 struct nid_stat *tmp = NULL, *tmp1;
1313 struct obd_device *obd = NULL;
1318 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1319 !exp->exp_obd->obd_nid_stats_hash_body)
1322 /* not test against zero because eric say:
1323 * You may only test nid against another nid, or LNET_NID_ANY. Anything else is
1325 if (!nid || *nid == LNET_NID_ANY)
1330 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash_body);
1332 OBD_ALLOC(tmp, sizeof(struct nid_stat));
1337 tmp->nid_obd = exp->exp_obd;
1338 tmp->nid_exp_ref_count = 1; /* need live in hash after destroy export */
1340 /* protect competitive add to list, not need locking on destroy */
1341 spin_lock(&obd->obd_nid_lock);
1342 list_add(&tmp->nid_list, &obd->obd_nid_stats);
1343 spin_unlock(&obd->obd_nid_lock);
1345 tmp1= lustre_hash_findadd_unique(obd->obd_nid_stats_hash_body, nid,
1347 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1348 tmp1, libcfs_nid2str(*nid), tmp->nid_exp_ref_count);
1351 exp->exp_nid_stats = tmp1;
1352 GOTO(destroy_new, rc = 0);
1354 /* not found - create */
1355 tmp->nid_proc = proc_mkdir(libcfs_nid2str(*nid),
1356 obd->obd_proc_exports_entry);
1357 if (!tmp->nid_proc) {
1358 CERROR("Error making export directory for"
1359 " nid %s\n", libcfs_nid2str(*nid));
1360 lustre_hash_delitem(obd->obd_nid_stats_hash_body, nid,
1362 GOTO(destroy_new, rc = -ENOMEM);
1365 rc = lprocfs_add_simple(tmp->nid_proc, "uuid",
1366 lprocfs_exp_rd_uuid, NULL, tmp);
1368 CWARN("Error adding the uuid file\n");
1370 exp->exp_nid_stats = tmp;
1375 spin_lock(&obd->obd_nid_lock);
1376 list_del(&tmp->nid_list);
1377 spin_unlock(&obd->obd_nid_lock);
1378 OBD_FREE(tmp, sizeof(struct nid_stat));
1382 int lprocfs_exp_cleanup(struct obd_export *exp)
1384 struct nid_stat *stat = exp->exp_nid_stats;
1389 stat->nid_exp_ref_count--;
1390 CDEBUG(D_INFO, "Put stat %p - %d\n", stat, stat->nid_exp_ref_count);
1392 exp->exp_nid_stats = NULL;
1393 lprocfs_free_stats(&exp->exp_ldlm_stats);
1394 lprocfs_free_stats(&exp->exp_ops_stats);
1399 int lprocfs_write_helper(const char *buffer, unsigned long count,
1402 return lprocfs_write_frac_helper(buffer, count, val, 1);
1405 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1408 char kernbuf[20], *end, *pbuf;
1410 if (count > (sizeof(kernbuf) - 1))
1413 if (copy_from_user(kernbuf, buffer, count))
1416 kernbuf[count] = '\0';
1423 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1427 if (end != NULL && *end == '.') {
1428 int temp_val, pow = 1;
1432 if (strlen(pbuf) > 5)
1433 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1435 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1438 for (i = 0; i < (end - pbuf); i++)
1441 *val += temp_val / pow;
1447 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, int mult)
1449 long decimal_val, frac_val;
1455 decimal_val = val / mult;
1456 prtn = snprintf(buffer, count, "%ld", decimal_val);
1457 frac_val = val % mult;
1459 if (prtn < (count - 4) && frac_val > 0) {
1461 int i, temp_mult = 1, frac_bits = 0;
1463 temp_frac = frac_val * 10;
1464 buffer[prtn++] = '.';
1465 while (frac_bits < 2 && (temp_frac / mult) < 1 ) { /*only reserved 2bits fraction*/
1466 buffer[prtn++] ='0';
1471 Need to think these cases :
1472 1. #echo x.00 > /proc/xxx output result : x
1473 2. #echo x.0x > /proc/xxx output result : x.0x
1474 3. #echo x.x0 > /proc/xxx output result : x.x
1475 4. #echo x.xx > /proc/xxx output result : x.xx
1476 Only reserved 2bits fraction.
1478 for (i = 0; i < (5 - prtn); i++)
1481 frac_bits = min((int)count - prtn, 3 - frac_bits);
1482 prtn += snprintf(buffer + prtn, frac_bits, "%ld", frac_val * temp_mult / mult);
1485 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1487 if (buffer[prtn] == '.') {
1494 buffer[prtn++] ='\n';
1498 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1500 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1503 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1504 __u64 *val, int mult)
1506 char kernbuf[22], *end, *pbuf;
1507 __u64 whole, frac = 0, units;
1508 unsigned frac_d = 1;
1510 if (count > (sizeof(kernbuf) - 1))
1513 if (copy_from_user(kernbuf, buffer, count))
1516 kernbuf[count] = '\0';
1523 whole = simple_strtoull(pbuf, &end, 10);
1527 if (end != NULL && *end == '.') {
1531 /* need to limit frac_d to a __u32 */
1532 if (strlen(pbuf) > 10)
1535 frac = simple_strtoull(pbuf, &end, 10);
1536 /* count decimal places */
1537 for (i = 0; i < (end - pbuf); i++)
1554 /* Specified units override the multiplier */
1556 mult = mult < 0 ? -units : units;
1559 do_div(frac, frac_d);
1560 *val = whole * mult + frac;
1564 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
1565 char *name, mode_t mode,
1566 struct file_operations *seq_fops, void *data)
1568 struct proc_dir_entry *entry;
1571 entry = create_proc_entry(name, mode, parent);
1574 entry->proc_fops = seq_fops;
1579 EXPORT_SYMBOL(lprocfs_seq_create);
1581 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
1583 struct file_operations *seq_fops,
1586 return (lprocfs_seq_create(dev->obd_proc_entry, name,
1587 mode, seq_fops, data));
1589 EXPORT_SYMBOL(lprocfs_obd_seq_create);
1591 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
1593 if (value >= OBD_HIST_MAX)
1594 value = OBD_HIST_MAX - 1;
1596 spin_lock(&oh->oh_lock);
1597 oh->oh_buckets[value]++;
1598 spin_unlock(&oh->oh_lock);
1600 EXPORT_SYMBOL(lprocfs_oh_tally);
1602 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
1606 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
1609 lprocfs_oh_tally(oh, val);
1611 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
1613 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
1615 unsigned long ret = 0;
1618 for (i = 0; i < OBD_HIST_MAX; i++)
1619 ret += oh->oh_buckets[i];
1622 EXPORT_SYMBOL(lprocfs_oh_sum);
1624 void lprocfs_oh_clear(struct obd_histogram *oh)
1626 spin_lock(&oh->oh_lock);
1627 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
1628 spin_unlock(&oh->oh_lock);
1630 EXPORT_SYMBOL(lprocfs_oh_clear);
1632 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
1633 int count, int *eof, void *data)
1635 struct obd_device *obd = data;
1638 LASSERT(obd != NULL);
1639 LASSERT(count >= 0);
1641 /* Set start of user data returned to
1642 page + off since the user may have
1643 requested to read much smaller than
1644 what we need to read */
1645 *start = page + off;
1647 /* We know we are allocated a page here.
1648 Also we know that this function will
1649 not need to write more than a page
1650 so we can truncate at CFS_PAGE_SIZE. */
1651 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
1653 /* Initialize the page */
1654 memset(page, 0, size);
1656 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
1658 if (obd->obd_max_recoverable_clients == 0) {
1659 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
1665 /* sampled unlocked, but really... */
1666 if (obd->obd_recovering == 0) {
1667 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
1669 if (lprocfs_obd_snprintf(&page, size, &len,
1670 "recovery_start: %lu\n",
1671 obd->obd_recovery_start) <= 0)
1673 if (lprocfs_obd_snprintf(&page, size, &len,
1674 "recovery_duration: %lu\n",
1675 obd->obd_recovery_end -
1676 obd->obd_recovery_start) <= 0)
1678 /* Number of clients that have completed recovery */
1679 if (lprocfs_obd_snprintf(&page, size, &len,
1680 "completed_clients: %d/%d\n",
1681 obd->obd_max_recoverable_clients -
1682 obd->obd_recoverable_clients,
1683 obd->obd_max_recoverable_clients) <= 0)
1685 if (lprocfs_obd_snprintf(&page, size, &len,
1686 "replayed_requests: %d\n",
1687 obd->obd_replayed_requests) <= 0)
1689 if (lprocfs_obd_snprintf(&page, size, &len,
1690 "last_transno: "LPD64"\n",
1691 obd->obd_next_recovery_transno - 1)<=0)
1696 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
1698 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
1699 obd->obd_recovery_start) <= 0)
1701 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
1702 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
1703 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
1705 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
1706 obd->obd_connected_clients,
1707 obd->obd_max_recoverable_clients) <= 0)
1709 /* Number of clients that have completed recovery */
1710 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d/%d\n",
1711 obd->obd_max_recoverable_clients -
1712 obd->obd_recoverable_clients,
1713 obd->obd_max_recoverable_clients) <= 0)
1715 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d/??\n",
1716 obd->obd_replayed_requests) <= 0)
1718 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
1719 obd->obd_requests_queued_for_recovery) <= 0)
1721 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
1722 obd->obd_next_recovery_transno) <= 0)
1728 return min(count, len - (int)off);
1730 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
1733 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
1734 int count, int *eof, void *data)
1736 struct obd_device *obd = (struct obd_device *)data;
1737 LASSERT(obd != NULL);
1739 return snprintf(page, count, "%lu\n",
1740 obd->obd_recovery_max_time);
1742 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
1744 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
1745 unsigned long count, void *data)
1747 struct obd_device *obd = (struct obd_device *)data;
1749 LASSERT(obd != NULL);
1751 rc = lprocfs_write_helper(buffer, count, &val);
1755 obd->obd_recovery_max_time = val;
1758 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
1759 #endif /* CRAY_XT3 */
1761 #ifdef HAVE_QUOTA_SUPPORT
1762 int lprocfs_quota_rd_bunit(char *page, char **start, off_t off, int count,
1763 int *eof, void *data)
1765 struct obd_device *obd = (struct obd_device *)data;
1766 LASSERT(obd != NULL);
1768 return snprintf(page, count, "%lu\n",
1769 obd->u.obt.obt_qctxt.lqc_bunit_sz);
1771 EXPORT_SYMBOL(lprocfs_quota_rd_bunit);
1773 int lprocfs_quota_wr_bunit(struct file *file, const char *buffer,
1774 unsigned long count, void *data)
1776 struct obd_device *obd = (struct obd_device *)data;
1778 LASSERT(obd != NULL);
1780 rc = lprocfs_write_helper(buffer, count, &val);
1784 if (val % QUOTABLOCK_SIZE ||
1785 val <= obd->u.obt.obt_qctxt.lqc_btune_sz)
1788 obd->u.obt.obt_qctxt.lqc_bunit_sz = val;
1791 EXPORT_SYMBOL(lprocfs_quota_wr_bunit);
1793 int lprocfs_quota_rd_btune(char *page, char **start, off_t off, int count,
1794 int *eof, void *data)
1796 struct obd_device *obd = (struct obd_device *)data;
1797 LASSERT(obd != NULL);
1799 return snprintf(page, count, "%lu\n",
1800 obd->u.obt.obt_qctxt.lqc_btune_sz);
1802 EXPORT_SYMBOL(lprocfs_quota_rd_btune);
1804 int lprocfs_quota_wr_btune(struct file *file, const char *buffer,
1805 unsigned long count, void *data)
1807 struct obd_device *obd = (struct obd_device *)data;
1809 LASSERT(obd != NULL);
1811 rc = lprocfs_write_helper(buffer, count, &val);
1815 if (val <= QUOTABLOCK_SIZE * MIN_QLIMIT || val % QUOTABLOCK_SIZE ||
1816 val >= obd->u.obt.obt_qctxt.lqc_bunit_sz)
1819 obd->u.obt.obt_qctxt.lqc_btune_sz = val;
1822 EXPORT_SYMBOL(lprocfs_quota_wr_btune);
1824 int lprocfs_quota_rd_iunit(char *page, char **start, off_t off, int count,
1825 int *eof, void *data)
1827 struct obd_device *obd = (struct obd_device *)data;
1828 LASSERT(obd != NULL);
1830 return snprintf(page, count, "%lu\n",
1831 obd->u.obt.obt_qctxt.lqc_iunit_sz);
1833 EXPORT_SYMBOL(lprocfs_quota_rd_iunit);
1835 int lprocfs_quota_wr_iunit(struct file *file, const char *buffer,
1836 unsigned long count, void *data)
1838 struct obd_device *obd = (struct obd_device *)data;
1840 LASSERT(obd != NULL);
1842 rc = lprocfs_write_helper(buffer, count, &val);
1846 if (val <= obd->u.obt.obt_qctxt.lqc_itune_sz)
1849 obd->u.obt.obt_qctxt.lqc_iunit_sz = val;
1852 EXPORT_SYMBOL(lprocfs_quota_wr_iunit);
1854 int lprocfs_quota_rd_itune(char *page, char **start, off_t off, int count,
1855 int *eof, void *data)
1857 struct obd_device *obd = (struct obd_device *)data;
1858 LASSERT(obd != NULL);
1860 return snprintf(page, count, "%lu\n",
1861 obd->u.obt.obt_qctxt.lqc_itune_sz);
1863 EXPORT_SYMBOL(lprocfs_quota_rd_itune);
1865 int lprocfs_quota_wr_itune(struct file *file, const char *buffer,
1866 unsigned long count, void *data)
1868 struct obd_device *obd = (struct obd_device *)data;
1870 LASSERT(obd != NULL);
1872 rc = lprocfs_write_helper(buffer, count, &val);
1876 if (val <= MIN_QLIMIT ||
1877 val >= obd->u.obt.obt_qctxt.lqc_iunit_sz)
1880 obd->u.obt.obt_qctxt.lqc_itune_sz = val;
1883 EXPORT_SYMBOL(lprocfs_quota_wr_itune);
1885 int lprocfs_quota_rd_switch_seconds(char *page, char **start, off_t off,
1886 int count, int *eof, void *data)
1888 struct obd_device *obd = (struct obd_device *)data;
1889 LASSERT(obd != NULL);
1891 return snprintf(page, count, "%d\n",
1892 obd->u.obt.obt_qctxt.lqc_switch_seconds);
1894 EXPORT_SYMBOL(lprocfs_quota_rd_switch_seconds);
1896 int lprocfs_quota_wr_switch_seconds(struct file *file, const char *buffer,
1897 unsigned long count, void *data)
1899 struct obd_device *obd = (struct obd_device *)data;
1901 LASSERT(obd != NULL);
1903 rc = lprocfs_write_helper(buffer, count, &val);
1910 obd->u.obt.obt_qctxt.lqc_switch_seconds = val;
1913 EXPORT_SYMBOL(lprocfs_quota_wr_switch_seconds);
1918 EXPORT_SYMBOL(lprocfs_register);
1919 EXPORT_SYMBOL(lprocfs_srch);
1920 EXPORT_SYMBOL(lprocfs_remove);
1921 EXPORT_SYMBOL(lprocfs_add_vars);
1922 EXPORT_SYMBOL(lprocfs_obd_setup);
1923 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1924 EXPORT_SYMBOL(lprocfs_add_simple);
1925 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1926 EXPORT_SYMBOL(lprocfs_alloc_stats);
1927 EXPORT_SYMBOL(lprocfs_free_stats);
1928 EXPORT_SYMBOL(lprocfs_clear_stats);
1929 EXPORT_SYMBOL(lprocfs_register_stats);
1930 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1931 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1932 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1933 EXPORT_SYMBOL(lprocfs_exp_setup);
1934 EXPORT_SYMBOL(lprocfs_exp_cleanup);
1936 EXPORT_SYMBOL(lprocfs_rd_u64);
1937 EXPORT_SYMBOL(lprocfs_rd_atomic);
1938 EXPORT_SYMBOL(lprocfs_wr_atomic);
1939 EXPORT_SYMBOL(lprocfs_rd_uint);
1940 EXPORT_SYMBOL(lprocfs_wr_uint);
1941 EXPORT_SYMBOL(lprocfs_rd_uuid);
1942 EXPORT_SYMBOL(lprocfs_rd_name);
1943 EXPORT_SYMBOL(lprocfs_rd_fstype);
1944 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
1945 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
1946 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1947 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1948 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1949 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1950 EXPORT_SYMBOL(lprocfs_rd_blksize);
1951 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
1952 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
1953 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
1954 EXPORT_SYMBOL(lprocfs_rd_filestotal);
1955 EXPORT_SYMBOL(lprocfs_rd_filesfree);
1957 EXPORT_SYMBOL(lprocfs_write_helper);
1958 EXPORT_SYMBOL(lprocfs_write_frac_helper);
1959 EXPORT_SYMBOL(lprocfs_read_frac_helper);
1960 EXPORT_SYMBOL(lprocfs_write_u64_helper);
1961 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);