Whamcloud - gitweb
LU-1347 style: removes obsolete EXPORT_SYMTAB macros
[fs/lustre-release.git] / lustre / obdclass / lprocfs_status.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2011, Whamcloud, Inc.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/obdclass/lprocfs_status.c
37  *
38  * Author: Hariharan Thantry <thantry@users.sourceforge.net>
39  */
40
41 #define DEBUG_SUBSYSTEM S_CLASS
42
43 #ifndef __KERNEL__
44 # include <liblustre.h>
45 #endif
46
47 #include <obd_class.h>
48 #include <lprocfs_status.h>
49 #include <lustre_fsfilt.h>
50 #include <lustre_log.h>
51 #include <lustre/lustre_idl.h>
52
53 #if defined(LPROCFS)
54
55 static int lprocfs_no_percpu_stats = 0;
56 CFS_MODULE_PARM(lprocfs_no_percpu_stats, "i", int, 0644,
57                 "Do not alloc percpu data for lprocfs stats");
58
59 #define MAX_STRING_SIZE 128
60
61 /* for bug 10866, global variable */
62 CFS_DECLARE_RWSEM(_lprocfs_lock);
63 EXPORT_SYMBOL(_lprocfs_lock);
64
65 int lprocfs_seq_release(struct inode *inode, struct file *file)
66 {
67         LPROCFS_EXIT();
68         return seq_release(inode, file);
69 }
70 EXPORT_SYMBOL(lprocfs_seq_release);
71
72 static struct proc_dir_entry *__lprocfs_srch(struct proc_dir_entry *head,
73                                              const char *name)
74 {
75         struct proc_dir_entry *temp;
76
77         if (head == NULL)
78                 return NULL;
79
80         temp = head->subdir;
81         while (temp != NULL) {
82                 if (strcmp(temp->name, name) == 0) {
83                         return temp;
84                 }
85
86                 temp = temp->next;
87         }
88         return NULL;
89 }
90
91 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
92                                     const char *name)
93 {
94         struct proc_dir_entry *temp;
95
96         LPROCFS_SRCH_ENTRY();
97         temp = __lprocfs_srch(head, name);
98         LPROCFS_SRCH_EXIT();
99         return temp;
100 }
101
102 /* lprocfs API calls */
103
104 /* Function that emulates snprintf but also has the side effect of advancing
105    the page pointer for the next write into the buffer, incrementing the total
106    length written to the buffer, and decrementing the size left in the
107    buffer. */
108 static int lprocfs_obd_snprintf(char **page, int end, int *len,
109                                 const char *format, ...)
110 {
111         va_list list;
112         int n;
113
114         if (*len >= end)
115                 return 0;
116
117         va_start(list, format);
118         n = vsnprintf(*page, end - *len, format, list);
119         va_end(list);
120
121         *page += n; *len += n;
122         return n;
123 }
124
125 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
126                                          char *name,
127                                          read_proc_t *read_proc,
128                                          write_proc_t *write_proc,
129                                          void *data,
130                                          struct file_operations *fops)
131 {
132         cfs_proc_dir_entry_t *proc;
133         mode_t mode = 0;
134
135         if (root == NULL || name == NULL)
136                 return ERR_PTR(-EINVAL);
137         if (read_proc)
138                 mode = 0444;
139         if (write_proc)
140                 mode |= 0200;
141         if (fops)
142                 mode = 0644;
143         LPROCFS_WRITE_ENTRY();
144         proc = create_proc_entry(name, mode, root);
145         if (!proc) {
146                 CERROR("LprocFS: No memory to create /proc entry %s", name);
147                 LPROCFS_WRITE_EXIT();
148                 return ERR_PTR(-ENOMEM);
149         }
150         proc->read_proc = read_proc;
151         proc->write_proc = write_proc;
152         proc->data = data;
153         if (fops)
154                 proc->proc_fops = fops;
155         LPROCFS_WRITE_EXIT();
156         return proc;
157 }
158
159 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
160                         struct proc_dir_entry *parent, const char *format, ...)
161 {
162         struct proc_dir_entry *entry;
163         char *dest;
164         va_list ap;
165
166         if (parent == NULL || format == NULL)
167                 return NULL;
168
169         OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
170         if (dest == NULL)
171                 return NULL;
172
173         va_start(ap, format);
174         vsnprintf(dest, MAX_STRING_SIZE, format, ap);
175         va_end(ap);
176
177         entry = proc_symlink(name, parent, dest);
178         if (entry == NULL)
179                 CERROR("LprocFS: Could not create symbolic link from %s to %s",
180                         name, dest);
181
182         OBD_FREE(dest, MAX_STRING_SIZE + 1);
183         return entry;
184 }
185
186 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
187                                  size_t size, loff_t *ppos)
188 {
189         struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
190         char *page, *start = NULL;
191         int rc = 0, eof = 1, count;
192
193         if (*ppos >= CFS_PAGE_SIZE)
194                 return 0;
195
196         page = (char *)__get_free_page(GFP_KERNEL);
197         if (page == NULL)
198                 return -ENOMEM;
199
200         if (LPROCFS_ENTRY_AND_CHECK(dp)) {
201                 rc = -ENOENT;
202                 goto out;
203         }
204
205         OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
206         if (dp->read_proc)
207                 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
208                                    &eof, dp->data);
209         LPROCFS_EXIT();
210         if (rc <= 0)
211                 goto out;
212
213         /* for lustre proc read, the read count must be less than PAGE_SIZE */
214         LASSERT(eof == 1);
215
216         if (start == NULL) {
217                 rc -= *ppos;
218                 if (rc < 0)
219                         rc = 0;
220                 if (rc == 0)
221                         goto out;
222                 start = page + *ppos;
223         } else if (start < page) {
224                 start = page;
225         }
226
227         count = (rc < size) ? rc : size;
228         if (cfs_copy_to_user(buf, start, count)) {
229                 rc = -EFAULT;
230                 goto out;
231         }
232         *ppos += count;
233
234 out:
235         free_page((unsigned long)page);
236         return rc;
237 }
238
239 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
240                                   size_t size, loff_t *ppos)
241 {
242         struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
243         int rc = -EIO;
244
245         if (LPROCFS_ENTRY_AND_CHECK(dp))
246                 return -ENOENT;
247         if (dp->write_proc)
248                 rc = dp->write_proc(f, buf, size, dp->data);
249         LPROCFS_EXIT();
250         return rc;
251 }
252
253 static struct file_operations lprocfs_generic_fops = {
254         .owner = THIS_MODULE,
255         .read = lprocfs_fops_read,
256         .write = lprocfs_fops_write,
257 };
258
259 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
260 {
261         struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
262         struct obd_device *obd = dp->data;
263
264         cfs_atomic_inc(&obd->obd_evict_inprogress);
265
266         return 0;
267 }
268
269 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
270 {
271         struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
272         struct obd_device *obd = dp->data;
273
274         cfs_atomic_dec(&obd->obd_evict_inprogress);
275         cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
276
277         return 0;
278 }
279
280 struct file_operations lprocfs_evict_client_fops = {
281         .owner = THIS_MODULE,
282         .read = lprocfs_fops_read,
283         .write = lprocfs_fops_write,
284         .open = lprocfs_evict_client_open,
285         .release = lprocfs_evict_client_release,
286 };
287 EXPORT_SYMBOL(lprocfs_evict_client_fops);
288
289 /**
290  * Add /proc entries.
291  *
292  * \param root [in]  The parent proc entry on which new entry will be added.
293  * \param list [in]  Array of proc entries to be added.
294  * \param data [in]  The argument to be passed when entries read/write routines
295  *                   are called through /proc file.
296  *
297  * \retval 0   on success
298  *         < 0 on error
299  */
300 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
301                      void *data)
302 {
303         int rc = 0;
304
305         if (root == NULL || list == NULL)
306                 return -EINVAL;
307
308         LPROCFS_WRITE_ENTRY();
309         while (list->name != NULL) {
310                 struct proc_dir_entry *cur_root, *proc;
311                 char *pathcopy, *cur, *next, pathbuf[64];
312                 int pathsize = strlen(list->name) + 1;
313
314                 proc = NULL;
315                 cur_root = root;
316
317                 /* need copy of path for strsep */
318                 if (strlen(list->name) > sizeof(pathbuf) - 1) {
319                         OBD_ALLOC(pathcopy, pathsize);
320                         if (pathcopy == NULL)
321                                 GOTO(out, rc = -ENOMEM);
322                 } else {
323                         pathcopy = pathbuf;
324                 }
325
326                 next = pathcopy;
327                 strcpy(pathcopy, list->name);
328
329                 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
330                         if (*cur =='\0') /* skip double/trailing "/" */
331                                 continue;
332
333                         proc = __lprocfs_srch(cur_root, cur);
334                         CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
335                                cur_root->name, cur, next,
336                                (proc ? "exists" : "new"));
337                         if (next != NULL) {
338                                 cur_root = (proc ? proc :
339                                             proc_mkdir(cur, cur_root));
340                         } else if (proc == NULL) {
341                                 mode_t mode = 0;
342                                 if (list->proc_mode != 0000) {
343                                         mode = list->proc_mode;
344                                 } else {
345                                         if (list->read_fptr)
346                                                 mode = 0444;
347                                         if (list->write_fptr)
348                                                 mode |= 0200;
349                                 }
350                                 proc = create_proc_entry(cur, mode, cur_root);
351                         }
352                 }
353
354                 if (pathcopy != pathbuf)
355                         OBD_FREE(pathcopy, pathsize);
356
357                 if (cur_root == NULL || proc == NULL) {
358                         CERROR("LprocFS: No memory to create /proc entry %s",
359                                list->name);
360                         GOTO(out, rc = -ENOMEM);
361                 }
362
363                 if (list->fops)
364                         proc->proc_fops = list->fops;
365                 else
366                         proc->proc_fops = &lprocfs_generic_fops;
367                 proc->read_proc = list->read_fptr;
368                 proc->write_proc = list->write_fptr;
369                 proc->data = (list->data ? list->data : data);
370                 list++;
371         }
372 out:
373         LPROCFS_WRITE_EXIT();
374         return rc;
375 }
376
377 void lprocfs_remove(struct proc_dir_entry **rooth)
378 {
379         struct proc_dir_entry *root = *rooth;
380         struct proc_dir_entry *temp = root;
381         struct proc_dir_entry *rm_entry;
382         struct proc_dir_entry *parent;
383
384         if (!root)
385                 return;
386         *rooth = NULL;
387
388         parent = root->parent;
389         LASSERT(parent != NULL);
390         LPROCFS_WRITE_ENTRY(); /* search vs remove race */
391
392         while (1) {
393                 while (temp->subdir != NULL)
394                         temp = temp->subdir;
395
396                 rm_entry = temp;
397                 temp = temp->parent;
398
399                 /* Memory corruption once caused this to fail, and
400                    without this LASSERT we would loop here forever. */
401                 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
402                          "0x%p  %s/%s len %d\n", rm_entry, temp->name,
403                          rm_entry->name, (int)strlen(rm_entry->name));
404
405 #ifdef HAVE_PROCFS_USERS
406                 /* if procfs uses user count to synchronize deletion of
407                  * proc entry, there is no protection for rm_entry->data,
408                  * then lprocfs_fops_read and lprocfs_fops_write maybe
409                  * call proc_dir_entry->read_proc (or write_proc) with
410                  * proc_dir_entry->data == NULL, then cause kernel Oops.
411                  * see bug19706 for detailed information */
412
413                 /* procfs won't free rm_entry->data if it isn't a LINK,
414                  * and Lustre won't use rm_entry->data if it is a LINK */
415                 if (S_ISLNK(rm_entry->mode))
416                         rm_entry->data = NULL;
417 #else
418                 /* Now, the rm_entry->deleted flags is protected
419                  * by _lprocfs_lock. */
420                 rm_entry->data = NULL;
421 #endif
422                 remove_proc_entry(rm_entry->name, temp);
423                 if (temp == parent)
424                         break;
425         }
426         LPROCFS_WRITE_EXIT();
427 }
428
429 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
430 {
431         LASSERT(parent != NULL);
432         remove_proc_entry(name, parent);
433 }
434
435 struct proc_dir_entry *lprocfs_register(const char *name,
436                                         struct proc_dir_entry *parent,
437                                         struct lprocfs_vars *list, void *data)
438 {
439         struct proc_dir_entry *newchild;
440
441         newchild = lprocfs_srch(parent, name);
442         if (newchild != NULL) {
443                 CERROR(" Lproc: Attempting to register %s more than once \n",
444                        name);
445                 return ERR_PTR(-EALREADY);
446         }
447
448         newchild = proc_mkdir(name, parent);
449         if (newchild != NULL && list != NULL) {
450                 int rc = lprocfs_add_vars(newchild, list, data);
451                 if (rc) {
452                         lprocfs_remove(&newchild);
453                         return ERR_PTR(rc);
454                 }
455         }
456         return newchild;
457 }
458
459 /* Generic callbacks */
460 int lprocfs_rd_uint(char *page, char **start, off_t off,
461                     int count, int *eof, void *data)
462 {
463         unsigned int *temp = data;
464         return snprintf(page, count, "%u\n", *temp);
465 }
466
467 int lprocfs_wr_uint(struct file *file, const char *buffer,
468                     unsigned long count, void *data)
469 {
470         unsigned *p = data;
471         char dummy[MAX_STRING_SIZE + 1], *end;
472         unsigned long tmp;
473
474         dummy[MAX_STRING_SIZE] = '\0';
475         if (cfs_copy_from_user(dummy, buffer, MAX_STRING_SIZE))
476                 return -EFAULT;
477
478         tmp = simple_strtoul(dummy, &end, 0);
479         if (dummy == end)
480                 return -EINVAL;
481
482         *p = (unsigned int)tmp;
483         return count;
484 }
485
486 int lprocfs_rd_u64(char *page, char **start, off_t off,
487                    int count, int *eof, void *data)
488 {
489         LASSERT(data != NULL);
490         *eof = 1;
491         return snprintf(page, count, LPU64"\n", *(__u64 *)data);
492 }
493
494 int lprocfs_rd_atomic(char *page, char **start, off_t off,
495                    int count, int *eof, void *data)
496 {
497         cfs_atomic_t *atom = data;
498         LASSERT(atom != NULL);
499         *eof = 1;
500         return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
501 }
502
503 int lprocfs_wr_atomic(struct file *file, const char *buffer,
504                       unsigned long count, void *data)
505 {
506         cfs_atomic_t *atm = data;
507         int val = 0;
508         int rc;
509
510         rc = lprocfs_write_helper(buffer, count, &val);
511         if (rc < 0)
512                 return rc;
513
514         if (val <= 0)
515                 return -ERANGE;
516
517         cfs_atomic_set(atm, val);
518         return count;
519 }
520
521 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
522                     int *eof, void *data)
523 {
524         struct obd_device *obd = data;
525
526         LASSERT(obd != NULL);
527         *eof = 1;
528         return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
529 }
530
531 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
532                     int *eof, void *data)
533 {
534         struct obd_device *dev = data;
535
536         LASSERT(dev != NULL);
537         LASSERT(dev->obd_name != NULL);
538         *eof = 1;
539         return snprintf(page, count, "%s\n", dev->obd_name);
540 }
541
542 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
543                       void *data)
544 {
545         struct obd_device *obd = data;
546
547         LASSERT(obd != NULL);
548         LASSERT(obd->obd_fsops != NULL);
549         LASSERT(obd->obd_fsops->fs_type != NULL);
550         return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
551 }
552
553 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
554                        int *eof, void *data)
555 {
556         struct obd_device *obd = data;
557         struct obd_statfs  osfs;
558         int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
559                             cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
560                             OBD_STATFS_NODELAY);
561         if (!rc) {
562                 *eof = 1;
563                 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
564         }
565         return rc;
566 }
567
568 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
569                            int *eof, void *data)
570 {
571         struct obd_device *obd = data;
572         struct obd_statfs  osfs;
573         int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
574                             cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
575                             OBD_STATFS_NODELAY);
576         if (!rc) {
577                 __u32 blk_size = osfs.os_bsize >> 10;
578                 __u64 result = osfs.os_blocks;
579
580                 while (blk_size >>= 1)
581                         result <<= 1;
582
583                 *eof = 1;
584                 rc = snprintf(page, count, LPU64"\n", result);
585         }
586         return rc;
587 }
588
589 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
590                           int *eof, void *data)
591 {
592         struct obd_device *obd = data;
593         struct obd_statfs  osfs;
594         int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
595                             cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
596                             OBD_STATFS_NODELAY);
597         if (!rc) {
598                 __u32 blk_size = osfs.os_bsize >> 10;
599                 __u64 result = osfs.os_bfree;
600
601                 while (blk_size >>= 1)
602                         result <<= 1;
603
604                 *eof = 1;
605                 rc = snprintf(page, count, LPU64"\n", result);
606         }
607         return rc;
608 }
609
610 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
611                            int *eof, void *data)
612 {
613         struct obd_device *obd = data;
614         struct obd_statfs  osfs;
615         int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
616                             cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
617                             OBD_STATFS_NODELAY);
618         if (!rc) {
619                 __u32 blk_size = osfs.os_bsize >> 10;
620                 __u64 result = osfs.os_bavail;
621
622                 while (blk_size >>= 1)
623                         result <<= 1;
624
625                 *eof = 1;
626                 rc = snprintf(page, count, LPU64"\n", result);
627         }
628         return rc;
629 }
630
631 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
632                           int *eof, void *data)
633 {
634         struct obd_device *obd = data;
635         struct obd_statfs  osfs;
636         int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
637                             cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
638                             OBD_STATFS_NODELAY);
639         if (!rc) {
640                 *eof = 1;
641                 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
642         }
643
644         return rc;
645 }
646
647 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
648                          int *eof, void *data)
649 {
650         struct obd_device *obd = data;
651         struct obd_statfs  osfs;
652         int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
653                             cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
654                             OBD_STATFS_NODELAY);
655         if (!rc) {
656                 *eof = 1;
657                 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
658         }
659         return rc;
660 }
661
662 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
663                            int *eof, void *data)
664 {
665         struct obd_device *obd = data;
666         struct obd_import *imp;
667         char *imp_state_name = NULL;
668         int rc = 0;
669
670         LASSERT(obd != NULL);
671         LPROCFS_CLIMP_CHECK(obd);
672         imp = obd->u.cli.cl_import;
673         imp_state_name = ptlrpc_import_state_name(imp->imp_state);
674         *eof = 1;
675         rc = snprintf(page, count, "%s\t%s%s\n",
676                       obd2cli_tgt(obd), imp_state_name,
677                       imp->imp_deactive ? "\tDEACTIVATED" : "");
678
679         LPROCFS_CLIMP_EXIT(obd);
680         return rc;
681 }
682
683 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
684                          int *eof,  void *data)
685 {
686         struct obd_device *obd = data;
687         struct ptlrpc_connection *conn;
688         int rc = 0;
689
690         LASSERT(obd != NULL);
691
692         LPROCFS_CLIMP_CHECK(obd);
693         conn = obd->u.cli.cl_import->imp_connection;
694         *eof = 1;
695         if (conn && obd->u.cli.cl_import) {
696                 rc = snprintf(page, count, "%s\n",
697                               conn->c_remote_uuid.uuid);
698         } else {
699                 rc = snprintf(page, count, "%s\n", "<none>");
700         }
701
702         LPROCFS_CLIMP_EXIT(obd);
703         return rc;
704 }
705
706 /** add up per-cpu counters */
707 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
708                            struct lprocfs_counter *cnt)
709 {
710         unsigned int num_cpu;
711         struct lprocfs_counter t;
712         struct lprocfs_counter *percpu_cntr;
713         int centry, i;
714
715         memset(cnt, 0, sizeof(*cnt));
716
717         if (stats == NULL) {
718                 /* set count to 1 to avoid divide-by-zero errs in callers */
719                 cnt->lc_count = 1;
720                 return;
721         }
722
723         cnt->lc_min = LC_MIN_INIT;
724
725         num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
726
727         for (i = 0; i < num_cpu; i++) {
728                 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
729
730                 do {
731                         centry = cfs_atomic_read(&percpu_cntr-> \
732                                                  lc_cntl.la_entry);
733                         t.lc_count = percpu_cntr->lc_count;
734                         t.lc_sum = percpu_cntr->lc_sum;
735                         t.lc_min = percpu_cntr->lc_min;
736                         t.lc_max = percpu_cntr->lc_max;
737                         t.lc_sumsquare = percpu_cntr->lc_sumsquare;
738                 } while (centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
739                                                    la_entry) &&
740                          centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
741                                                    la_exit));
742                 cnt->lc_count += t.lc_count;
743                 cnt->lc_sum += t.lc_sum;
744                 if (t.lc_min < cnt->lc_min)
745                         cnt->lc_min = t.lc_min;
746                 if (t.lc_max > cnt->lc_max)
747                         cnt->lc_max = t.lc_max;
748                 cnt->lc_sumsquare += t.lc_sumsquare;
749         }
750
751         cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
752         lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU);
753 }
754
755 /**
756  * Append a space separated list of current set flags to str.
757  */
758 #define flag2str(flag) \
759         if (imp->imp_##flag && max - len > 0) \
760              len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
761 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
762 {
763         int len = 0;
764
765         if (imp->imp_obd->obd_no_recov)
766                 len += snprintf(str, max - len, "no_recov");
767
768         flag2str(invalid);
769         flag2str(deactive);
770         flag2str(replayable);
771         flag2str(pingable);
772         return len;
773 }
774 #undef flags2str
775
776 static const char *obd_connect_names[] = {
777         "read_only",
778         "lov_index",
779         "unused",
780         "write_grant",
781         "server_lock",
782         "version",
783         "request_portal",
784         "acl",
785         "xattr",
786         "create_on_write",
787         "truncate_lock",
788         "initial_transno",
789         "inode_bit_locks",
790         "join_file(obsolete)",
791         "getattr_by_fid",
792         "no_oh_for_devices",
793         "remote_client",
794         "remote_client_by_force",
795         "max_byte_per_rpc",
796         "64bit_qdata",
797         "mds_capability",
798         "oss_capability",
799         "early_lock_cancel",
800         "som",
801         "adaptive_timeouts",
802         "lru_resize",
803         "mds_mds_connection",
804         "real_conn",
805         "change_qunit_size",
806         "alt_checksum_algorithm",
807         "fid_is_enabled",
808         "version_recovery",
809         "pools",
810         "grant_shrink",
811         "skip_orphan",
812         "large_ea",
813         "full20",
814         "layout_lock",
815         "64bithash",
816         "object_max_bytes",
817         "imp_recov",
818         "jobstats",
819         "umask",
820         "einprogress",
821         "grant_param",
822         NULL
823 };
824
825 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
826 {
827         __u64 mask = 1;
828         int i, ret = 0;
829
830         for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
831                 if (flags & mask)
832                         ret += snprintf(page + ret, count - ret, "%s%s",
833                                         ret ? sep : "", obd_connect_names[i]);
834         }
835         if (flags & ~(mask - 1))
836                 ret += snprintf(page + ret, count - ret,
837                                 "%sunknown flags "LPX64,
838                                 ret ? sep : "", flags & ~(mask - 1));
839         return ret;
840 }
841 EXPORT_SYMBOL(obd_connect_flags2str);
842
843 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
844                       int *eof, void *data)
845 {
846         struct lprocfs_counter ret;
847         struct obd_device *obd = (struct obd_device *)data;
848         struct obd_import *imp;
849         struct obd_import_conn *conn;
850         int i, j, k, rw = 0;
851
852         LASSERT(obd != NULL);
853         LPROCFS_CLIMP_CHECK(obd);
854         imp = obd->u.cli.cl_import;
855         *eof = 1;
856
857         i = snprintf(page, count,
858                      "import:\n"
859                      "    name: %s\n"
860                      "    target: %s\n"
861                      "    state: %s\n"
862                      "    instance: %u\n"
863                      "    connect_flags: [",
864                      obd->obd_name,
865                      obd2cli_tgt(obd),
866                      ptlrpc_import_state_name(imp->imp_state),
867                      imp->imp_connect_data.ocd_instance);
868         i += obd_connect_flags2str(page + i, count - i,
869                                    imp->imp_connect_data.ocd_connect_flags,
870                                    ", ");
871         i += snprintf(page + i, count - i,
872                       "]\n"
873                       "    import_flags: [");
874         i += obd_import_flags2str(imp, page + i, count - i);
875
876         i += snprintf(page + i, count - i,
877                       "]\n"
878                       "    connection:\n"
879                       "       failover_nids: [");
880         cfs_spin_lock(&imp->imp_lock);
881         j = 0;
882         cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
883                 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
884                               libcfs_nid2str(conn->oic_conn->c_peer.nid));
885                 j++;
886         }
887         cfs_spin_unlock(&imp->imp_lock);
888         i += snprintf(page + i, count - i,
889                       "]\n"
890                       "       current_connection: %s\n"
891                       "       connection_attempts: %u\n"
892                       "       generation: %u\n"
893                       "       in-progress_invalidations: %u\n",
894                       libcfs_nid2str(imp->imp_connection->c_peer.nid),
895                       imp->imp_conn_cnt,
896                       imp->imp_generation,
897                       cfs_atomic_read(&imp->imp_inval_count));
898
899         lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
900         if (ret.lc_count != 0) {
901                 /* first argument to do_div MUST be __u64 */
902                 __u64 sum = ret.lc_sum;
903                 do_div(sum, ret.lc_count);
904                 ret.lc_sum = sum;
905         } else
906                 ret.lc_sum = 0;
907         i += snprintf(page + i, count - i,
908                       "    rpcs:\n"
909                       "       inflight: %u\n"
910                       "       unregistering: %u\n"
911                       "       timeouts: %u\n"
912                       "       avg_waittime: "LPU64" %s\n",
913                       cfs_atomic_read(&imp->imp_inflight),
914                       cfs_atomic_read(&imp->imp_unregistering),
915                       cfs_atomic_read(&imp->imp_timeouts),
916                       ret.lc_sum, ret.lc_units);
917
918         k = 0;
919         for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
920                 if (imp->imp_at.iat_portal[j] == 0)
921                         break;
922                 k = max_t(unsigned int, k,
923                           at_get(&imp->imp_at.iat_service_estimate[j]));
924         }
925         i += snprintf(page + i, count - i,
926                       "    service_estimates:\n"
927                       "       services: %u sec\n"
928                       "       network: %u sec\n",
929                       k,
930                       at_get(&imp->imp_at.iat_net_latency));
931
932         i += snprintf(page + i, count - i,
933                       "    transactions:\n"
934                       "       last_replay: "LPU64"\n"
935                       "       peer_committed: "LPU64"\n"
936                       "       last_checked: "LPU64"\n",
937                       imp->imp_last_replay_transno,
938                       imp->imp_peer_committed_transno,
939                       imp->imp_last_transno_checked);
940
941         /* avg data rates */
942         for (rw = 0; rw <= 1; rw++) {
943                 lprocfs_stats_collect(obd->obd_svc_stats,
944                                       PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
945                                       &ret);
946                 if (ret.lc_sum > 0 && ret.lc_count > 0) {
947                         /* first argument to do_div MUST be __u64 */
948                         __u64 sum = ret.lc_sum;
949                         do_div(sum, ret.lc_count);
950                         ret.lc_sum = sum;
951                         i += snprintf(page + i, count - i,
952                                       "    %s_data_averages:\n"
953                                       "       bytes_per_rpc: "LPU64"\n",
954                                       rw ? "write" : "read",
955                                       ret.lc_sum);
956                 }
957                 k = (int)ret.lc_sum;
958                 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
959                 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
960                 if (ret.lc_sum > 0 && ret.lc_count != 0) {
961                         /* first argument to do_div MUST be __u64 */
962                         __u64 sum = ret.lc_sum;
963                         do_div(sum, ret.lc_count);
964                         ret.lc_sum = sum;
965                         i += snprintf(page + i, count - i,
966                                       "       %s_per_rpc: "LPU64"\n",
967                                       ret.lc_units, ret.lc_sum);
968                         j = (int)ret.lc_sum;
969                         if (j > 0)
970                                 i += snprintf(page + i, count - i,
971                                               "       MB_per_sec: %u.%.02u\n",
972                                               k / j, (100 * k / j) % 100);
973                 }
974         }
975
976         LPROCFS_CLIMP_EXIT(obd);
977         return i;
978 }
979
980 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
981                       int *eof, void *data)
982 {
983         struct obd_device *obd = (struct obd_device *)data;
984         struct obd_import *imp;
985         int i, j, k;
986
987         LASSERT(obd != NULL);
988         LPROCFS_CLIMP_CHECK(obd);
989         imp = obd->u.cli.cl_import;
990         *eof = 1;
991
992         i = snprintf(page, count, "current_state: %s\n",
993                      ptlrpc_import_state_name(imp->imp_state));
994         i += snprintf(page + i, count - i,
995                       "state_history:\n");
996         k = imp->imp_state_hist_idx;
997         for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
998                 struct import_state_hist *ish =
999                         &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1000                 if (ish->ish_state == 0)
1001                         continue;
1002                 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1003                               ish->ish_time,
1004                               ptlrpc_import_state_name(ish->ish_state));
1005         }
1006
1007         LPROCFS_CLIMP_EXIT(obd);
1008         return i;
1009 }
1010
1011 int lprocfs_at_hist_helper(char *page, int count, int rc,
1012                            struct adaptive_timeout *at)
1013 {
1014         int i;
1015         for (i = 0; i < AT_BINS; i++)
1016                 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1017         rc += snprintf(page + rc, count - rc, "\n");
1018         return rc;
1019 }
1020
1021 /* See also ptlrpc_lprocfs_rd_timeouts */
1022 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1023                         int *eof, void *data)
1024 {
1025         struct obd_device *obd = (struct obd_device *)data;
1026         struct obd_import *imp;
1027         unsigned int cur, worst;
1028         time_t now, worstt;
1029         struct dhms ts;
1030         int i, rc = 0;
1031
1032         LASSERT(obd != NULL);
1033         LPROCFS_CLIMP_CHECK(obd);
1034         imp = obd->u.cli.cl_import;
1035         *eof = 1;
1036
1037         now = cfs_time_current_sec();
1038
1039         /* Some network health info for kicks */
1040         s2dhms(&ts, now - imp->imp_last_reply_time);
1041         rc += snprintf(page + rc, count - rc,
1042                        "%-10s : %ld, "DHMS_FMT" ago\n",
1043                        "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1044
1045         cur = at_get(&imp->imp_at.iat_net_latency);
1046         worst = imp->imp_at.iat_net_latency.at_worst_ever;
1047         worstt = imp->imp_at.iat_net_latency.at_worst_time;
1048         s2dhms(&ts, now - worstt);
1049         rc += snprintf(page + rc, count - rc,
1050                        "%-10s : cur %3u  worst %3u (at %ld, "DHMS_FMT" ago) ",
1051                        "network", cur, worst, worstt, DHMS_VARS(&ts));
1052         rc = lprocfs_at_hist_helper(page, count, rc,
1053                                     &imp->imp_at.iat_net_latency);
1054
1055         for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1056                 if (imp->imp_at.iat_portal[i] == 0)
1057                         break;
1058                 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1059                 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1060                 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1061                 s2dhms(&ts, now - worstt);
1062                 rc += snprintf(page + rc, count - rc,
1063                                "portal %-2d  : cur %3u  worst %3u (at %ld, "
1064                                DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1065                                cur, worst, worstt, DHMS_VARS(&ts));
1066                 rc = lprocfs_at_hist_helper(page, count, rc,
1067                                           &imp->imp_at.iat_service_estimate[i]);
1068         }
1069
1070         LPROCFS_CLIMP_EXIT(obd);
1071         return rc;
1072 }
1073
1074 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1075                              int count, int *eof, void *data)
1076 {
1077         struct obd_device *obd = data;
1078         __u64 flags;
1079         int ret = 0;
1080
1081         LPROCFS_CLIMP_CHECK(obd);
1082         flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1083         ret = snprintf(page, count, "flags="LPX64"\n", flags);
1084         ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1085         ret += snprintf(page + ret, count - ret, "\n");
1086         LPROCFS_CLIMP_EXIT(obd);
1087         return ret;
1088 }
1089 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1090
1091 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1092                            int *eof,  void *data)
1093 {
1094         struct obd_device *obd = data;
1095
1096         LASSERT(obd != NULL);
1097         *eof = 1;
1098         return snprintf(page, count, "%u\n", obd->obd_num_exports);
1099 }
1100
1101 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1102                        int *eof, void *data)
1103 {
1104         struct obd_type *class = (struct obd_type*) data;
1105
1106         LASSERT(class != NULL);
1107         *eof = 1;
1108         return snprintf(page, count, "%d\n", class->typ_refcnt);
1109 }
1110
1111 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1112 {
1113         int rc = 0;
1114
1115         LASSERT(obd != NULL);
1116         LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1117         LASSERT(obd->obd_type->typ_procroot != NULL);
1118
1119         obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1120                                                obd->obd_type->typ_procroot,
1121                                                list, obd);
1122         if (IS_ERR(obd->obd_proc_entry)) {
1123                 rc = PTR_ERR(obd->obd_proc_entry);
1124                 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1125                 obd->obd_proc_entry = NULL;
1126         }
1127         return rc;
1128 }
1129
1130 int lprocfs_obd_cleanup(struct obd_device *obd)
1131 {
1132         if (!obd)
1133                 return -EINVAL;
1134         if (obd->obd_proc_exports_entry) {
1135                 /* Should be no exports left */
1136                 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1137                 lprocfs_remove(&obd->obd_proc_exports_entry);
1138                 obd->obd_proc_exports_entry = NULL;
1139         }
1140         if (obd->obd_proc_entry) {
1141                 lprocfs_remove(&obd->obd_proc_entry);
1142                 obd->obd_proc_entry = NULL;
1143         }
1144         return 0;
1145 }
1146
1147 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1148 {
1149         CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1150                client_stat->nid_proc, client_stat->nid_stats,
1151                client_stat->nid_brw_stats);
1152
1153         LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1154                  "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1155                  atomic_read(&client_stat->nid_exp_ref_count));
1156
1157         if (client_stat->nid_proc)
1158                 lprocfs_remove(&client_stat->nid_proc);
1159
1160         if (client_stat->nid_stats)
1161                 lprocfs_free_stats(&client_stat->nid_stats);
1162
1163         if (client_stat->nid_brw_stats)
1164                 OBD_FREE_PTR(client_stat->nid_brw_stats);
1165
1166         if (client_stat->nid_ldlm_stats)
1167                 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1168
1169         OBD_FREE_PTR(client_stat);
1170         return;
1171
1172 }
1173
1174 void lprocfs_free_per_client_stats(struct obd_device *obd)
1175 {
1176         cfs_hash_t *hash = obd->obd_nid_stats_hash;
1177         struct nid_stat *stat;
1178         ENTRY;
1179
1180         /* we need extra list - because hash_exit called to early */
1181         /* not need locking because all clients is died */
1182         while (!cfs_list_empty(&obd->obd_nid_stats)) {
1183                 stat = cfs_list_entry(obd->obd_nid_stats.next,
1184                                       struct nid_stat, nid_list);
1185                 cfs_list_del_init(&stat->nid_list);
1186                 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1187                 lprocfs_free_client_stats(stat);
1188         }
1189         EXIT;
1190 }
1191
1192 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1193                                           enum lprocfs_stats_flags flags)
1194 {
1195         struct lprocfs_stats *stats;
1196         unsigned int percpusize;
1197         unsigned int i, j;
1198         unsigned int num_cpu;
1199
1200         if (num == 0)
1201                 return NULL;
1202
1203         if (lprocfs_no_percpu_stats != 0)
1204                 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1205
1206         if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1207                 num_cpu = 1;
1208         else
1209                 num_cpu = cfs_num_possible_cpus();
1210
1211         OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1212         if (stats == NULL)
1213                 return NULL;
1214
1215         if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1216                 stats->ls_flags = flags;
1217                 cfs_spin_lock_init(&stats->ls_lock);
1218                 /* Use this lock only if there are no percpu areas */
1219         } else {
1220                 stats->ls_flags = 0;
1221         }
1222
1223         percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1224         if (num_cpu > 1)
1225                 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1226
1227         for (i = 0; i < num_cpu; i++) {
1228                 OBD_ALLOC(stats->ls_percpu[i], percpusize);
1229                 if (stats->ls_percpu[i] == NULL) {
1230                         for (j = 0; j < i; j++) {
1231                                 OBD_FREE(stats->ls_percpu[j], percpusize);
1232                                 stats->ls_percpu[j] = NULL;
1233                         }
1234                         break;
1235                 }
1236         }
1237         if (stats->ls_percpu[0] == NULL) {
1238                 OBD_FREE(stats, offsetof(typeof(*stats),
1239                                          ls_percpu[num_cpu]));
1240                 return NULL;
1241         }
1242
1243         stats->ls_num = num;
1244         return stats;
1245 }
1246
1247 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1248 {
1249         struct lprocfs_stats *stats = *statsh;
1250         unsigned int num_cpu;
1251         unsigned int percpusize;
1252         unsigned int i;
1253
1254         if (stats == NULL || stats->ls_num == 0)
1255                 return;
1256         *statsh = NULL;
1257
1258         if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1259                 num_cpu = 1;
1260         else
1261                 num_cpu = cfs_num_possible_cpus();
1262
1263         percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1264         if (num_cpu > 1)
1265                 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1266         for (i = 0; i < num_cpu; i++)
1267                 OBD_FREE(stats->ls_percpu[i], percpusize);
1268         OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1269 }
1270
1271 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1272 {
1273         struct lprocfs_counter *percpu_cntr;
1274         int i,j;
1275         unsigned int num_cpu;
1276
1277         num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1278
1279         for (i = 0; i < num_cpu; i++) {
1280                 for (j = 0; j < stats->ls_num; j++) {
1281                         percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1282                         cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1283                         percpu_cntr->lc_count = 0;
1284                         percpu_cntr->lc_sum = 0;
1285                         percpu_cntr->lc_min = LC_MIN_INIT;
1286                         percpu_cntr->lc_max = 0;
1287                         percpu_cntr->lc_sumsquare = 0;
1288                         cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1289                 }
1290         }
1291
1292         lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU);
1293 }
1294
1295 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1296                                        size_t len, loff_t *off)
1297 {
1298         struct seq_file *seq = file->private_data;
1299         struct lprocfs_stats *stats = seq->private;
1300
1301         lprocfs_clear_stats(stats);
1302
1303         return len;
1304 }
1305
1306 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1307 {
1308         struct lprocfs_stats *stats = p->private;
1309         /* return 1st cpu location */
1310         return (*pos >= stats->ls_num) ? NULL :
1311                 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1312 }
1313
1314 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1315 {
1316 }
1317
1318 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1319 {
1320         struct lprocfs_stats *stats = p->private;
1321         ++*pos;
1322         return (*pos >= stats->ls_num) ? NULL :
1323                 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1324 }
1325
1326 /* seq file export of one lprocfs counter */
1327 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1328 {
1329        struct lprocfs_stats *stats = p->private;
1330        struct lprocfs_counter *cntr = v;
1331        struct lprocfs_counter ret;
1332        int idx, rc = 0;
1333
1334        if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1335                struct timeval now;
1336                cfs_gettimeofday(&now);
1337                rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1338                                "snapshot_time", now.tv_sec, now.tv_usec);
1339                if (rc < 0)
1340                        return rc;
1341        }
1342        idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1343
1344        lprocfs_stats_collect(stats, idx, &ret);
1345
1346        if (ret.lc_count == 0)
1347                goto out;
1348
1349        rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1350                        ret.lc_count, cntr->lc_units);
1351
1352        if (rc < 0)
1353                goto out;
1354
1355        if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1356                rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1357                                ret.lc_min, ret.lc_max, ret.lc_sum);
1358                if (rc < 0)
1359                        goto out;
1360                if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1361                        rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1362                if (rc < 0)
1363                        goto out;
1364        }
1365        rc = seq_printf(p, "\n");
1366  out:
1367        return (rc < 0) ? rc : 0;
1368 }
1369
1370 struct seq_operations lprocfs_stats_seq_sops = {
1371         start: lprocfs_stats_seq_start,
1372         stop:  lprocfs_stats_seq_stop,
1373         next:  lprocfs_stats_seq_next,
1374         show:  lprocfs_stats_seq_show,
1375 };
1376
1377 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1378 {
1379         struct proc_dir_entry *dp = PDE(inode);
1380         struct seq_file *seq;
1381         int rc;
1382
1383         if (LPROCFS_ENTRY_AND_CHECK(dp))
1384                 return -ENOENT;
1385
1386         rc = seq_open(file, &lprocfs_stats_seq_sops);
1387         if (rc) {
1388                 LPROCFS_EXIT();
1389                 return rc;
1390         }
1391         seq = file->private_data;
1392         seq->private = dp->data;
1393         return 0;
1394 }
1395
1396 struct file_operations lprocfs_stats_seq_fops = {
1397         .owner   = THIS_MODULE,
1398         .open    = lprocfs_stats_seq_open,
1399         .read    = seq_read,
1400         .write   = lprocfs_stats_seq_write,
1401         .llseek  = seq_lseek,
1402         .release = lprocfs_seq_release,
1403 };
1404
1405 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1406                            struct lprocfs_stats *stats)
1407 {
1408         struct proc_dir_entry *entry;
1409         LASSERT(root != NULL);
1410
1411         LPROCFS_WRITE_ENTRY();
1412         entry = create_proc_entry(name, 0644, root);
1413         if (entry) {
1414                 entry->proc_fops = &lprocfs_stats_seq_fops;
1415                 entry->data = stats;
1416         }
1417
1418         LPROCFS_WRITE_EXIT();
1419
1420         if (entry == NULL)
1421                 return -ENOMEM;
1422
1423         return 0;
1424 }
1425
1426 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1427                           unsigned conf, const char *name, const char *units)
1428 {
1429         struct lprocfs_counter *c;
1430         int i;
1431         unsigned int num_cpu;
1432
1433         LASSERT(stats != NULL);
1434
1435         num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1436
1437         for (i = 0; i < num_cpu; i++) {
1438                 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1439                 c->lc_config = conf;
1440                 c->lc_count = 0;
1441                 c->lc_sum = 0;
1442                 c->lc_min = LC_MIN_INIT;
1443                 c->lc_max = 0;
1444                 c->lc_name = name;
1445                 c->lc_units = units;
1446         }
1447
1448         lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU);
1449 }
1450 EXPORT_SYMBOL(lprocfs_counter_init);
1451
1452 #define LPROCFS_OBD_OP_INIT(base, stats, op)                               \
1453 do {                                                                       \
1454         unsigned int coffset = base + OBD_COUNTER_OFFSET(op);              \
1455         LASSERT(coffset < stats->ls_num);                                  \
1456         lprocfs_counter_init(stats, coffset, 0, #op, "reqs");              \
1457 } while (0)
1458
1459 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1460 {
1461         LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1462         LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1463         LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1464         LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1465         LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1466         LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1467         LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1468         LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1469         LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1470         LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1471         LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1472         LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1473         LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1474         LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1475         LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1476         LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1477         LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1478         LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1479         LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1480         LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1481         LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1482         LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1483         LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1484         LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1485         LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1486         LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1487         LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1488         LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1489         LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1490         LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1491         LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1492         LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1493         LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1494         LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1495         LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1496         LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1497         LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1498         LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1499         LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1500         LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1501         LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1502         LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1503         LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1504         LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1505         LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1506         LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1507         LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1508         LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1509         LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1510         LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1511         LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1512         LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1513         LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1514         LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1515         LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1516         LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1517         LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1518         LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1519         LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1520         LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1521         LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1522         LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1523         LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1524         LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1525         LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1526         LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1527         LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1528         LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1529         LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1530 }
1531
1532 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1533 {
1534         struct lprocfs_stats *stats;
1535         unsigned int num_stats;
1536         int rc, i;
1537
1538         LASSERT(obd->obd_stats == NULL);
1539         LASSERT(obd->obd_proc_entry != NULL);
1540         LASSERT(obd->obd_cntr_base == 0);
1541
1542         num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1543                 num_private_stats - 1 /* o_owner */;
1544         stats = lprocfs_alloc_stats(num_stats, 0);
1545         if (stats == NULL)
1546                 return -ENOMEM;
1547
1548         lprocfs_init_ops_stats(num_private_stats, stats);
1549
1550         for (i = num_private_stats; i < num_stats; i++) {
1551                 /* If this LBUGs, it is likely that an obd
1552                  * operation was added to struct obd_ops in
1553                  * <obd.h>, and that the corresponding line item
1554                  * LPROCFS_OBD_OP_INIT(.., .., opname)
1555                  * is missing from the list above. */
1556                 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1557                          "Missing obd_stat initializer obd_op "
1558                          "operation at offset %d.\n", i - num_private_stats);
1559         }
1560         rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1561         if (rc < 0) {
1562                 lprocfs_free_stats(&stats);
1563         } else {
1564                 obd->obd_stats  = stats;
1565                 obd->obd_cntr_base = num_private_stats;
1566         }
1567         return rc;
1568 }
1569
1570 void lprocfs_free_obd_stats(struct obd_device *obd)
1571 {
1572         if (obd->obd_stats)
1573                 lprocfs_free_stats(&obd->obd_stats);
1574 }
1575
1576 #define LPROCFS_MD_OP_INIT(base, stats, op)                             \
1577 do {                                                                    \
1578         unsigned int coffset = base + MD_COUNTER_OFFSET(op);            \
1579         LASSERT(coffset < stats->ls_num);                               \
1580         lprocfs_counter_init(stats, coffset, 0, #op, "reqs");           \
1581 } while (0)
1582
1583 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1584 {
1585         LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1586         LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1587         LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1588         LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1589         LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1590         LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1591         LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1592         LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1593         LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1594         LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1595         LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1596         LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1597         LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1598         LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1599         LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1600         LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1601         LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1602         LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1603         LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1604         LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1605         LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1606         LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1607         LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1608         LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1609         LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1610         LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1611         LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1612         LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1613         LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1614         LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1615         LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1616         LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1617 }
1618
1619 int lprocfs_alloc_md_stats(struct obd_device *obd,
1620                            unsigned num_private_stats)
1621 {
1622         struct lprocfs_stats *stats;
1623         unsigned int num_stats;
1624         int rc, i;
1625
1626         LASSERT(obd->md_stats == NULL);
1627         LASSERT(obd->obd_proc_entry != NULL);
1628         LASSERT(obd->md_cntr_base == 0);
1629
1630         num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1631                     num_private_stats;
1632         stats = lprocfs_alloc_stats(num_stats, 0);
1633         if (stats == NULL)
1634                 return -ENOMEM;
1635
1636         lprocfs_init_mps_stats(num_private_stats, stats);
1637
1638         for (i = num_private_stats; i < num_stats; i++) {
1639                 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1640                         CERROR("Missing md_stat initializer md_op "
1641                                "operation at offset %d. Aborting.\n",
1642                                i - num_private_stats);
1643                         LBUG();
1644                 }
1645         }
1646         rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1647         if (rc < 0) {
1648                 lprocfs_free_stats(&stats);
1649         } else {
1650                 obd->md_stats  = stats;
1651                 obd->md_cntr_base = num_private_stats;
1652         }
1653         return rc;
1654 }
1655
1656 void lprocfs_free_md_stats(struct obd_device *obd)
1657 {
1658         struct lprocfs_stats *stats = obd->md_stats;
1659
1660         if (stats != NULL) {
1661                 obd->md_stats = NULL;
1662                 obd->md_cntr_base = 0;
1663                 lprocfs_free_stats(&stats);
1664         }
1665 }
1666
1667 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1668 {
1669         lprocfs_counter_init(ldlm_stats,
1670                              LDLM_ENQUEUE - LDLM_FIRST_OPC,
1671                              0, "ldlm_enqueue", "reqs");
1672         lprocfs_counter_init(ldlm_stats,
1673                              LDLM_CONVERT - LDLM_FIRST_OPC,
1674                              0, "ldlm_convert", "reqs");
1675         lprocfs_counter_init(ldlm_stats,
1676                              LDLM_CANCEL - LDLM_FIRST_OPC,
1677                              0, "ldlm_cancel", "reqs");
1678         lprocfs_counter_init(ldlm_stats,
1679                              LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1680                              0, "ldlm_bl_callback", "reqs");
1681         lprocfs_counter_init(ldlm_stats,
1682                              LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1683                              0, "ldlm_cp_callback", "reqs");
1684         lprocfs_counter_init(ldlm_stats,
1685                              LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1686                              0, "ldlm_gl_callback", "reqs");
1687 }
1688
1689 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1690                          int *eof,  void *data)
1691 {
1692         struct obd_export *exp = data;
1693         LASSERT(exp != NULL);
1694         *eof = 1;
1695         return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1696 }
1697
1698 struct exp_uuid_cb_data {
1699         char                   *page;
1700         int                     count;
1701         int                    *eof;
1702         int                    *len;
1703 };
1704
1705 static void
1706 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1707                             int count, int *eof, int *len)
1708 {
1709         cb_data->page = page;
1710         cb_data->count = count;
1711         cb_data->eof = eof;
1712         cb_data->len = len;
1713 }
1714
1715 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1716                            cfs_hlist_node_t *hnode, void *cb_data)
1717
1718 {
1719         struct obd_export *exp = cfs_hash_object(hs, hnode);
1720         struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1721
1722         if (exp->exp_nid_stats)
1723                 *data->len += snprintf((data->page + *data->len),
1724                                        data->count, "%s\n",
1725                                        obd_uuid2str(&exp->exp_client_uuid));
1726         return 0;
1727 }
1728
1729 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1730                         int *eof,  void *data)
1731 {
1732         struct nid_stat *stats = (struct nid_stat *)data;
1733         struct exp_uuid_cb_data cb_data;
1734         struct obd_device *obd = stats->nid_obd;
1735         int len = 0;
1736
1737         *eof = 1;
1738         page[0] = '\0';
1739         lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1740         cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1741                               lprocfs_exp_print_uuid, &cb_data);
1742         return (*cb_data.len);
1743 }
1744
1745 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1746                            cfs_hlist_node_t *hnode, void *cb_data)
1747
1748 {
1749         struct exp_uuid_cb_data *data = cb_data;
1750         struct obd_export       *exp = cfs_hash_object(hs, hnode);
1751
1752         if (exp->exp_lock_hash != NULL) {
1753                 if (!*data->len) {
1754                         *data->len += cfs_hash_debug_header(data->page,
1755                                                             data->count);
1756                 }
1757                 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1758                                                  data->count);
1759         }
1760
1761         return 0;
1762 }
1763
1764 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1765                         int *eof,  void *data)
1766 {
1767         struct nid_stat *stats = (struct nid_stat *)data;
1768         struct exp_uuid_cb_data cb_data;
1769         struct obd_device *obd = stats->nid_obd;
1770         int len = 0;
1771
1772         *eof = 1;
1773         page[0] = '\0';
1774         lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1775
1776         cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1777                               lprocfs_exp_print_hash, &cb_data);
1778         return (*cb_data.len);
1779 }
1780
1781 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1782                                         int count, int *eof,  void *data)
1783 {
1784         *eof = 1;
1785         return snprintf(page, count, "%s\n",
1786                         "Write into this file to clear all nid stats and "
1787                         "stale nid entries");
1788 }
1789 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1790
1791 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1792 {
1793         struct nid_stat *stat = obj;
1794         int i;
1795         ENTRY;
1796
1797         CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1798         if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1799                 /* object has only hash references. */
1800                 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1801                 cfs_list_move(&stat->nid_list, data);
1802                 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
1803                 RETURN(1);
1804         }
1805         /* we has reference to object - only clear data*/
1806         if (stat->nid_stats)
1807                 lprocfs_clear_stats(stat->nid_stats);
1808
1809         if (stat->nid_brw_stats) {
1810                 for (i = 0; i < BRW_LAST; i++)
1811                         lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1812         }
1813         RETURN(0);
1814 }
1815
1816 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1817                                   unsigned long count, void *data)
1818 {
1819         struct obd_device *obd = (struct obd_device *)data;
1820         struct nid_stat *client_stat;
1821         CFS_LIST_HEAD(free_list);
1822
1823         cfs_hash_cond_del(obd->obd_nid_stats_hash,
1824                           lprocfs_nid_stats_clear_write_cb, &free_list);
1825
1826         while (!cfs_list_empty(&free_list)) {
1827                 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1828                                              nid_list);
1829                 cfs_list_del_init(&client_stat->nid_list);
1830                 lprocfs_free_client_stats(client_stat);
1831         }
1832
1833         return count;
1834 }
1835 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1836
1837 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1838 {
1839         struct nid_stat *new_stat, *old_stat;
1840         struct obd_device *obd = NULL;
1841         cfs_proc_dir_entry_t *entry;
1842         char *buffer = NULL;
1843         int rc = 0;
1844         ENTRY;
1845
1846         *newnid = 0;
1847
1848         if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1849             !exp->exp_obd->obd_nid_stats_hash)
1850                 RETURN(-EINVAL);
1851
1852         /* not test against zero because eric say:
1853          * You may only test nid against another nid, or LNET_NID_ANY.
1854          * Anything else is nonsense.*/
1855         if (!nid || *nid == LNET_NID_ANY)
1856                 RETURN(0);
1857
1858         obd = exp->exp_obd;
1859
1860         CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1861
1862         OBD_ALLOC_PTR(new_stat);
1863         if (new_stat == NULL)
1864                 RETURN(-ENOMEM);
1865
1866         new_stat->nid               = *nid;
1867         new_stat->nid_obd           = exp->exp_obd;
1868         /* we need set default refcount to 1 to balance obd_disconnect */
1869         cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
1870
1871         old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1872                                            nid, &new_stat->nid_hash);
1873         CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1874                old_stat, libcfs_nid2str(*nid),
1875                cfs_atomic_read(&new_stat->nid_exp_ref_count));
1876
1877         /* We need to release old stats because lprocfs_exp_cleanup() hasn't
1878          * been and will never be called. */
1879         if (exp->exp_nid_stats) {
1880                 nidstat_putref(exp->exp_nid_stats);
1881                 exp->exp_nid_stats = NULL;
1882         }
1883
1884         /* Return -EALREADY here so that we know that the /proc
1885          * entry already has been created */
1886         if (old_stat != new_stat) {
1887                 exp->exp_nid_stats = old_stat;
1888                 GOTO(destroy_new, rc = -EALREADY);
1889         }
1890         /* not found - create */
1891         OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
1892         if (buffer == NULL)
1893                 GOTO(destroy_new, rc = -ENOMEM);
1894
1895         memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
1896         new_stat->nid_proc = lprocfs_register(buffer,
1897                                               obd->obd_proc_exports_entry,
1898                                               NULL, NULL);
1899         OBD_FREE(buffer, LNET_NIDSTR_SIZE);
1900
1901         if (new_stat->nid_proc == NULL) {
1902                 CERROR("Error making export directory for nid %s\n",
1903                        libcfs_nid2str(*nid));
1904                 GOTO(destroy_new_ns, rc = -ENOMEM);
1905         }
1906
1907         entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1908                                    lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1909         if (IS_ERR(entry)) {
1910                 CWARN("Error adding the NID stats file\n");
1911                 rc = PTR_ERR(entry);
1912                 GOTO(destroy_new_ns, rc);
1913         }
1914
1915         entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1916                                    lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1917         if (IS_ERR(entry)) {
1918                 CWARN("Error adding the hash file\n");
1919                 rc = PTR_ERR(entry);
1920                 GOTO(destroy_new_ns, rc);
1921         }
1922
1923         exp->exp_nid_stats = new_stat;
1924         *newnid = 1;
1925         /* protect competitive add to list, not need locking on destroy */
1926         cfs_spin_lock(&obd->obd_nid_lock);
1927         cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1928         cfs_spin_unlock(&obd->obd_nid_lock);
1929
1930         RETURN(rc);
1931
1932 destroy_new_ns:
1933         if (new_stat->nid_proc != NULL)
1934                 lprocfs_remove(&new_stat->nid_proc);
1935         cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1936
1937 destroy_new:
1938         nidstat_putref(new_stat);
1939         OBD_FREE_PTR(new_stat);
1940         RETURN(rc);
1941 }
1942
1943 int lprocfs_exp_cleanup(struct obd_export *exp)
1944 {
1945         struct nid_stat *stat = exp->exp_nid_stats;
1946
1947         if(!stat || !exp->exp_obd)
1948                 RETURN(0);
1949
1950         nidstat_putref(exp->exp_nid_stats);
1951         exp->exp_nid_stats = NULL;
1952
1953         return 0;
1954 }
1955
1956 int lprocfs_write_helper(const char *buffer, unsigned long count,
1957                          int *val)
1958 {
1959         return lprocfs_write_frac_helper(buffer, count, val, 1);
1960 }
1961
1962 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1963                               int *val, int mult)
1964 {
1965         char kernbuf[20], *end, *pbuf;
1966
1967         if (count > (sizeof(kernbuf) - 1))
1968                 return -EINVAL;
1969
1970         if (cfs_copy_from_user(kernbuf, buffer, count))
1971                 return -EFAULT;
1972
1973         kernbuf[count] = '\0';
1974         pbuf = kernbuf;
1975         if (*pbuf == '-') {
1976                 mult = -mult;
1977                 pbuf++;
1978         }
1979
1980         *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1981         if (pbuf == end)
1982                 return -EINVAL;
1983
1984         if (end != NULL && *end == '.') {
1985                 int temp_val, pow = 1;
1986                 int i;
1987
1988                 pbuf = end + 1;
1989                 if (strlen(pbuf) > 5)
1990                         pbuf[5] = '\0'; /*only allow 5bits fractional*/
1991
1992                 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1993
1994                 if (pbuf < end) {
1995                         for (i = 0; i < (end - pbuf); i++)
1996                                 pow *= 10;
1997
1998                         *val += temp_val / pow;
1999                 }
2000         }
2001         return 0;
2002 }
2003
2004 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2005                              int mult)
2006 {
2007         long decimal_val, frac_val;
2008         int prtn;
2009
2010         if (count < 10)
2011                 return -EINVAL;
2012
2013         decimal_val = val / mult;
2014         prtn = snprintf(buffer, count, "%ld", decimal_val);
2015         frac_val = val % mult;
2016
2017         if (prtn < (count - 4) && frac_val > 0) {
2018                 long temp_frac;
2019                 int i, temp_mult = 1, frac_bits = 0;
2020
2021                 temp_frac = frac_val * 10;
2022                 buffer[prtn++] = '.';
2023                 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2024                         /* only reserved 2 bits fraction */
2025                         buffer[prtn++] ='0';
2026                         temp_frac *= 10;
2027                         frac_bits++;
2028                 }
2029                 /*
2030                  * Need to think these cases :
2031                  *      1. #echo x.00 > /proc/xxx       output result : x
2032                  *      2. #echo x.0x > /proc/xxx       output result : x.0x
2033                  *      3. #echo x.x0 > /proc/xxx       output result : x.x
2034                  *      4. #echo x.xx > /proc/xxx       output result : x.xx
2035                  *      Only reserved 2 bits fraction.
2036                  */
2037                 for (i = 0; i < (5 - prtn); i++)
2038                         temp_mult *= 10;
2039
2040                 frac_bits = min((int)count - prtn, 3 - frac_bits);
2041                 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2042                                  frac_val * temp_mult / mult);
2043
2044                 prtn--;
2045                 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2046                         prtn--;
2047                         if (buffer[prtn] == '.') {
2048                                 prtn--;
2049                                 break;
2050                         }
2051                 }
2052                 prtn++;
2053         }
2054         buffer[prtn++] ='\n';
2055         return prtn;
2056 }
2057
2058 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2059 {
2060         return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2061 }
2062
2063 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2064                               __u64 *val, int mult)
2065 {
2066         char kernbuf[22], *end, *pbuf;
2067         __u64 whole, frac = 0, units;
2068         unsigned frac_d = 1;
2069
2070         if (count > (sizeof(kernbuf) - 1))
2071                 return -EINVAL;
2072
2073         if (cfs_copy_from_user(kernbuf, buffer, count))
2074                 return -EFAULT;
2075
2076         kernbuf[count] = '\0';
2077         pbuf = kernbuf;
2078         if (*pbuf == '-') {
2079                 mult = -mult;
2080                 pbuf++;
2081         }
2082
2083         whole = simple_strtoull(pbuf, &end, 10);
2084         if (pbuf == end)
2085                 return -EINVAL;
2086
2087         if (end != NULL && *end == '.') {
2088                 int i;
2089                 pbuf = end + 1;
2090
2091                 /* need to limit frac_d to a __u32 */
2092                 if (strlen(pbuf) > 10)
2093                         pbuf[10] = '\0';
2094
2095                 frac = simple_strtoull(pbuf, &end, 10);
2096                 /* count decimal places */
2097                 for (i = 0; i < (end - pbuf); i++)
2098                         frac_d *= 10;
2099         }
2100
2101         units = 1;
2102         switch(*end) {
2103         case 'p': case 'P':
2104                 units <<= 10;
2105         case 't': case 'T':
2106                 units <<= 10;
2107         case 'g': case 'G':
2108                 units <<= 10;
2109         case 'm': case 'M':
2110                 units <<= 10;
2111         case 'k': case 'K':
2112                 units <<= 10;
2113         }
2114         /* Specified units override the multiplier */
2115         if (units)
2116                 mult = mult < 0 ? -units : units;
2117
2118         frac *= mult;
2119         do_div(frac, frac_d);
2120         *val = whole * mult + frac;
2121         return 0;
2122 }
2123
2124 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2125                        struct file_operations *seq_fops, void *data)
2126 {
2127         struct proc_dir_entry *entry;
2128         ENTRY;
2129
2130         LPROCFS_WRITE_ENTRY();
2131         entry = create_proc_entry(name, mode, parent);
2132         if (entry) {
2133                 entry->proc_fops = seq_fops;
2134                 entry->data = data;
2135         }
2136         LPROCFS_WRITE_EXIT();
2137
2138         if (entry == NULL)
2139                 RETURN(-ENOMEM);
2140
2141         RETURN(0);
2142 }
2143 EXPORT_SYMBOL(lprocfs_seq_create);
2144
2145 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2146                                       mode_t mode,
2147                                       struct file_operations *seq_fops,
2148                                       void *data)
2149 {
2150         return (lprocfs_seq_create(dev->obd_proc_entry, name,
2151                                    mode, seq_fops, data));
2152 }
2153 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2154
2155 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2156 {
2157         if (value >= OBD_HIST_MAX)
2158                 value = OBD_HIST_MAX - 1;
2159
2160         cfs_spin_lock(&oh->oh_lock);
2161         oh->oh_buckets[value]++;
2162         cfs_spin_unlock(&oh->oh_lock);
2163 }
2164 EXPORT_SYMBOL(lprocfs_oh_tally);
2165
2166 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2167 {
2168         unsigned int val;
2169
2170         for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2171                 ;
2172
2173         lprocfs_oh_tally(oh, val);
2174 }
2175 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2176
2177 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2178 {
2179         unsigned long ret = 0;
2180         int i;
2181
2182         for (i = 0; i < OBD_HIST_MAX; i++)
2183                 ret +=  oh->oh_buckets[i];
2184         return ret;
2185 }
2186 EXPORT_SYMBOL(lprocfs_oh_sum);
2187
2188 void lprocfs_oh_clear(struct obd_histogram *oh)
2189 {
2190         cfs_spin_lock(&oh->oh_lock);
2191         memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2192         cfs_spin_unlock(&oh->oh_lock);
2193 }
2194 EXPORT_SYMBOL(lprocfs_oh_clear);
2195
2196 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2197                         int count, int *eof, void *data)
2198 {
2199         struct obd_device *obd = data;
2200         int c = 0;
2201
2202         if (obd == NULL)
2203                 return 0;
2204
2205         c += cfs_hash_debug_header(page, count);
2206         c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2207         c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2208         c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2209 #ifdef HAVE_QUOTA_SUPPORT
2210         if (obd->u.obt.obt_qctxt.lqc_lqs_hash)
2211                 c += cfs_hash_debug_str(obd->u.obt.obt_qctxt.lqc_lqs_hash,
2212                                         page + c, count - c);
2213 #endif
2214
2215         return c;
2216 }
2217 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2218
2219 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2220                                    int count, int *eof, void *data)
2221 {
2222         struct obd_device *obd = data;
2223         int len = 0, size;
2224
2225         LASSERT(obd != NULL);
2226         LASSERT(count >= 0);
2227
2228         /* Set start of user data returned to
2229            page + off since the user may have
2230            requested to read much smaller than
2231            what we need to read */
2232         *start = page + off;
2233
2234         /* We know we are allocated a page here.
2235            Also we know that this function will
2236            not need to write more than a page
2237            so we can truncate at CFS_PAGE_SIZE.  */
2238         size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2239
2240         /* Initialize the page */
2241         memset(page, 0, size);
2242
2243         if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2244                 goto out;
2245         if (obd->obd_max_recoverable_clients == 0) {
2246                 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2247                         goto out;
2248
2249                 goto fclose;
2250         }
2251
2252         /* sampled unlocked, but really... */
2253         if (obd->obd_recovering == 0) {
2254                 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2255                         goto out;
2256                 if (lprocfs_obd_snprintf(&page, size, &len,
2257                                          "recovery_start: %lu\n",
2258                                          obd->obd_recovery_start) <= 0)
2259                         goto out;
2260                 if (lprocfs_obd_snprintf(&page, size, &len,
2261                                          "recovery_duration: %lu\n",
2262                                          obd->obd_recovery_end -
2263                                          obd->obd_recovery_start) <= 0)
2264                         goto out;
2265                 /* Number of clients that have completed recovery */
2266                 if (lprocfs_obd_snprintf(&page, size, &len,
2267                                          "completed_clients: %d/%d\n",
2268                                          obd->obd_max_recoverable_clients -
2269                                          obd->obd_stale_clients,
2270                                          obd->obd_max_recoverable_clients) <= 0)
2271                         goto out;
2272                 if (lprocfs_obd_snprintf(&page, size, &len,
2273                                          "replayed_requests: %d\n",
2274                                          obd->obd_replayed_requests) <= 0)
2275                         goto out;
2276                 if (lprocfs_obd_snprintf(&page, size, &len,
2277                                          "last_transno: "LPD64"\n",
2278                                          obd->obd_next_recovery_transno - 1)<=0)
2279                         goto out;
2280                 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2281                                          obd->obd_version_recov ? "ON" : "OFF")<=0)
2282                         goto out;
2283                 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2284                                          obd->obd_no_ir ? "OFF" : "ON") <= 0)
2285                         goto out;
2286                 goto fclose;
2287         }
2288
2289         if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2290                 goto out;
2291         if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2292                                  obd->obd_recovery_start) <= 0)
2293                 goto out;
2294         if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2295                                  cfs_time_current_sec() >=
2296                                  obd->obd_recovery_start +
2297                                  obd->obd_recovery_timeout ? 0 :
2298                                  obd->obd_recovery_start +
2299                                  obd->obd_recovery_timeout -
2300                                  cfs_time_current_sec()) <= 0)
2301                 goto out;
2302         if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2303                                  cfs_atomic_read(&obd->obd_connected_clients),
2304                                  obd->obd_max_recoverable_clients) <= 0)
2305                 goto out;
2306         /* Number of clients that have completed recovery */
2307         if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2308                                  cfs_atomic_read(&obd->obd_req_replay_clients))
2309                 <= 0)
2310                 goto out;
2311         if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2312                                  cfs_atomic_read(&obd->obd_lock_replay_clients))
2313                 <=0)
2314                 goto out;
2315         if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2316                                  cfs_atomic_read(&obd->obd_connected_clients) -
2317                                  cfs_atomic_read(&obd->obd_lock_replay_clients))
2318                 <=0)
2319                 goto out;
2320         if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2321                                  obd->obd_stale_clients) <= 0)
2322                 goto out;
2323         if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2324                                  obd->obd_replayed_requests) <= 0)
2325                 goto out;
2326         if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2327                                  obd->obd_requests_queued_for_recovery) <= 0)
2328                 goto out;
2329
2330         if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2331                                  obd->obd_next_recovery_transno) <= 0)
2332                 goto out;
2333
2334 fclose:
2335         *eof = 1;
2336 out:
2337         return min(count, len - (int)off);
2338 }
2339 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2340
2341 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2342                              int count, int *eof, void *data)
2343 {
2344         struct obd_device *obd = (struct obd_device *)data;
2345         LASSERT(obd != NULL);
2346
2347         return snprintf(page, count, "%d\n",
2348                         obd->obd_recovery_ir_factor);
2349 }
2350 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2351
2352 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2353                              unsigned long count, void *data)
2354 {
2355         struct obd_device *obd = (struct obd_device *)data;
2356         int val, rc;
2357         LASSERT(obd != NULL);
2358
2359         rc = lprocfs_write_helper(buffer, count, &val);
2360         if (rc)
2361                 return rc;
2362
2363         if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2364                 return -EINVAL;
2365
2366         obd->obd_recovery_ir_factor = val;
2367         return count;
2368 }
2369 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2370
2371 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2372                                       int count, int *eof, void *data)
2373 {
2374         struct obd_device *obd = (struct obd_device *)data;
2375         LASSERT(obd != NULL);
2376
2377         return snprintf(page, count, "%d\n",
2378                         obd->obd_recovery_timeout);
2379 }
2380 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2381
2382 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2383                                       unsigned long count, void *data)
2384 {
2385         struct obd_device *obd = (struct obd_device *)data;
2386         int val, rc;
2387         LASSERT(obd != NULL);
2388
2389         rc = lprocfs_write_helper(buffer, count, &val);
2390         if (rc)
2391                 return rc;
2392
2393         obd->obd_recovery_timeout = val;
2394         return count;
2395 }
2396 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2397
2398 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2399                                       int count, int *eof, void *data)
2400 {
2401         struct obd_device *obd = data;
2402         LASSERT(obd != NULL);
2403
2404         return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2405 }
2406 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2407
2408 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2409                                       unsigned long count, void *data)
2410 {
2411         struct obd_device *obd = data;
2412         int val, rc;
2413         LASSERT(obd != NULL);
2414
2415         rc = lprocfs_write_helper(buffer, count, &val);
2416         if (rc)
2417                 return rc;
2418
2419         obd->obd_recovery_time_hard = val;
2420         return count;
2421 }
2422 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2423
2424 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2425                           int count, int *eof, void *data)
2426 {
2427         struct obd_device *obd = (struct obd_device *)data;
2428
2429         LASSERT(obd != NULL);
2430         LASSERT(obd->u.obt.obt_vfsmnt->mnt_devname);
2431         *eof = 1;
2432         return snprintf(page, count, "%s\n",
2433                         obd->u.obt.obt_vfsmnt->mnt_devname);
2434 }
2435 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2436
2437 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2438                                      int count, int *eof, void *data)
2439 {
2440         struct obd_device *dev = data;
2441         struct client_obd *cli = &dev->u.cli;
2442         int rc;
2443
2444         client_obd_list_lock(&cli->cl_loi_list_lock);
2445         rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2446         client_obd_list_unlock(&cli->cl_loi_list_lock);
2447         return rc;
2448 }
2449 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2450
2451 int lprocfs_obd_wr_max_pages_per_rpc(struct file *file, const char *buffer,
2452                                      unsigned long count, void *data)
2453 {
2454         struct obd_device *dev = data;
2455         struct client_obd *cli = &dev->u.cli;
2456         struct obd_connect_data *ocd = &cli->cl_import->imp_connect_data;
2457         int val, rc;
2458
2459         rc = lprocfs_write_helper(buffer, count, &val);
2460         if (rc)
2461                 return rc;
2462
2463         LPROCFS_CLIMP_CHECK(dev);
2464         if (val < 1 || val > ocd->ocd_brw_size >> CFS_PAGE_SHIFT) {
2465                 LPROCFS_CLIMP_EXIT(dev);
2466                 return -ERANGE;
2467         }
2468         client_obd_list_lock(&cli->cl_loi_list_lock);
2469         cli->cl_max_pages_per_rpc = val;
2470         client_obd_list_unlock(&cli->cl_loi_list_lock);
2471
2472         LPROCFS_CLIMP_EXIT(dev);
2473         return count;
2474 }
2475 EXPORT_SYMBOL(lprocfs_obd_wr_max_pages_per_rpc);
2476
2477 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2478                                int count, int *eof, void *data)
2479 {
2480         struct obd_device *obd = (struct obd_device *)data;
2481         struct obd_device_target *target = &obd->u.obt;
2482
2483         LASSERT(obd != NULL);
2484         LASSERT(target->obt_magic == OBT_MAGIC);
2485         *eof = 1;
2486         return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2487 }
2488 EXPORT_SYMBOL(lprocfs_target_rd_instance);
2489
2490 EXPORT_SYMBOL(lprocfs_register);
2491 EXPORT_SYMBOL(lprocfs_srch);
2492 EXPORT_SYMBOL(lprocfs_remove);
2493 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2494 EXPORT_SYMBOL(lprocfs_add_vars);
2495 EXPORT_SYMBOL(lprocfs_obd_setup);
2496 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2497 EXPORT_SYMBOL(lprocfs_add_simple);
2498 EXPORT_SYMBOL(lprocfs_add_symlink);
2499 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2500 EXPORT_SYMBOL(lprocfs_alloc_stats);
2501 EXPORT_SYMBOL(lprocfs_free_stats);
2502 EXPORT_SYMBOL(lprocfs_clear_stats);
2503 EXPORT_SYMBOL(lprocfs_register_stats);
2504 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2505 EXPORT_SYMBOL(lprocfs_init_mps_stats);
2506 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2507 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2508 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2509 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2510 EXPORT_SYMBOL(lprocfs_free_md_stats);
2511 EXPORT_SYMBOL(lprocfs_exp_setup);
2512 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2513
2514 EXPORT_SYMBOL(lprocfs_rd_u64);
2515 EXPORT_SYMBOL(lprocfs_rd_atomic);
2516 EXPORT_SYMBOL(lprocfs_wr_atomic);
2517 EXPORT_SYMBOL(lprocfs_rd_uint);
2518 EXPORT_SYMBOL(lprocfs_wr_uint);
2519 EXPORT_SYMBOL(lprocfs_rd_uuid);
2520 EXPORT_SYMBOL(lprocfs_rd_name);
2521 EXPORT_SYMBOL(lprocfs_rd_fstype);
2522 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2523 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2524 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2525 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2526 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2527 EXPORT_SYMBOL(lprocfs_rd_import);
2528 EXPORT_SYMBOL(lprocfs_rd_state);
2529 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2530 EXPORT_SYMBOL(lprocfs_rd_blksize);
2531 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2532 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2533 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2534 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2535 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2536
2537 EXPORT_SYMBOL(lprocfs_write_helper);
2538 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2539 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2540 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2541 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2542 EXPORT_SYMBOL(lprocfs_stats_collect);
2543 #endif /* LPROCFS*/