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