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