Whamcloud - gitweb
b=16715 NFS cannot files in HEAD, MDS crashing
[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 CFS_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 (cfs_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         cfs_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         cfs_atomic_dec(&obd->obd_evict_inprogress);
249         cfs_waitq_signal(&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 (cfs_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         cfs_atomic_t *atom = data;
453         LASSERT(atom != NULL);
454         *eof = 1;
455         return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
456 }
457
458 int lprocfs_wr_atomic(struct file *file, const char *buffer,
459                       unsigned long count, void *data)
460 {
461         cfs_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         cfs_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() - CFS_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() - CFS_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() - CFS_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() - CFS_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() - CFS_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() - CFS_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         *eof = 1;
638         if (conn && obd->u.cli.cl_import) {
639                 rc = snprintf(page, count, "%s\n",
640                               conn->c_remote_uuid.uuid);
641         } else {
642                 rc = snprintf(page, count, "%s\n", "<none>");
643         }
644
645         LPROCFS_CLIMP_EXIT(obd);
646         return rc;
647 }
648
649 /** add up per-cpu counters */
650 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
651                            struct lprocfs_counter *cnt)
652 {
653         unsigned int num_cpu;
654         struct lprocfs_counter t;
655         struct lprocfs_counter *percpu_cntr;
656         int centry, i;
657
658         memset(cnt, 0, sizeof(*cnt));
659
660         if (stats == NULL) {
661                 /* set count to 1 to avoid divide-by-zero errs in callers */
662                 cnt->lc_count = 1;
663                 return;
664         }
665
666         cnt->lc_min = LC_MIN_INIT;
667
668         if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
669                 num_cpu = 1;
670         else
671                 num_cpu = cfs_num_possible_cpus();
672
673         for (i = 0; i < num_cpu; i++) {
674                 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
675
676                 do {
677                         centry = cfs_atomic_read(&percpu_cntr-> \
678                                                  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 != cfs_atomic_read(&percpu_cntr->lc_cntl. \
685                                                    la_entry) &&
686                          centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
687                                                    la_exit));
688                 cnt->lc_count += t.lc_count;
689                 cnt->lc_sum += t.lc_sum;
690                 if (t.lc_min < cnt->lc_min)
691                         cnt->lc_min = t.lc_min;
692                 if (t.lc_max > cnt->lc_max)
693                         cnt->lc_max = t.lc_max;
694                 cnt->lc_sumsquare += t.lc_sumsquare;
695         }
696
697         cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
698 }
699
700 /**
701  * Append a space separated list of current set flags to str.
702  */
703 #define flag2str(flag) \
704         if (imp->imp_##flag && max - len > 0) \
705              len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
706 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
707 {
708         int len = 0;
709
710         if (imp->imp_obd->obd_no_recov)
711                 len += snprintf(str, max - len, "no_recov");
712
713         flag2str(invalid);
714         flag2str(deactive);
715         flag2str(replayable);
716         flag2str(pingable);
717         flag2str(recon_bk);
718         flag2str(last_recon);
719         return len;
720 }
721 #undef flags2str
722
723 static const char *obd_connect_names[] = {
724         "read_only",
725         "lov_index",
726         "unused",
727         "write_grant",
728         "server_lock",
729         "version",
730         "request_portal",
731         "acl",
732         "xattr",
733         "create_on_write",
734         "truncate_lock",
735         "initial_transno",
736         "inode_bit_locks",
737         "join_file(obsolete)",
738         "getattr_by_fid",
739         "no_oh_for_devices",
740         "remote_client",
741         "remote_client_by_force",
742         "max_byte_per_rpc",
743         "64bit_qdata",
744         "mds_capability",
745         "oss_capability",
746         "early_lock_cancel",
747         "som",
748         "adaptive_timeouts",
749         "lru_resize",
750         "mds_mds_connection",
751         "real_conn",
752         "change_qunit_size",
753         "alt_checksum_algorithm",
754         "fid_is_enabled",
755         "version_recovery",
756         "pools",
757         "grant_shrink",
758         "skip_orphan",
759         NULL
760 };
761
762 static int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
763 {
764         __u64 mask = 1;
765         int i, ret = 0;
766
767         for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
768                 if (flags & mask)
769                         ret += snprintf(page + ret, count - ret, "%s%s",
770                                         ret ? sep : "", obd_connect_names[i]);
771         }
772         if (flags & ~(mask - 1))
773                 ret += snprintf(page + ret, count - ret,
774                                 "%sunknown flags "LPX64,
775                                 ret ? sep : "", flags & ~(mask - 1));
776         return ret;
777 }
778
779 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
780                       int *eof, void *data)
781 {
782         struct lprocfs_counter ret;
783         struct obd_device *obd = (struct obd_device *)data;
784         struct obd_import *imp;
785         int i, j, k, rw = 0;
786
787         LASSERT(obd != NULL);
788         LPROCFS_CLIMP_CHECK(obd);
789         imp = obd->u.cli.cl_import;
790         *eof = 1;
791
792         i = snprintf(page, count,
793                      "import:\n"
794                      "    name: %s\n"
795                      "    target: %s\n"
796                      "    current_connection: %s\n"
797                      "    state: %s\n"
798                      "    connect_flags: [",
799                      obd->obd_name,
800                      obd2cli_tgt(obd),
801                      imp->imp_connection->c_remote_uuid.uuid,
802                      ptlrpc_import_state_name(imp->imp_state));
803         i += obd_connect_flags2str(page + i, count - i,
804                                    imp->imp_connect_data.ocd_connect_flags,
805                                    ", ");
806         i += snprintf(page + i, count - i,
807                       "]\n"
808                       "    import_flags: [");
809         i += obd_import_flags2str(imp, page + i, count - i);
810
811         i += snprintf(page + i, count - i,
812                       "]\n"
813                       "    connection:\n"
814                       "       connection_attempts: %u\n"
815                       "       generation: %u\n"
816                       "       in-progress_invalidations: %u\n",
817                       imp->imp_conn_cnt,
818                       imp->imp_generation,
819                       cfs_atomic_read(&imp->imp_inval_count));
820
821         lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
822         do_div(ret.lc_sum, ret.lc_count);
823         i += snprintf(page + i, count - i,
824                       "    rpcs:\n"
825                       "       inflight: %u\n"
826                       "       unregistering: %u\n"
827                       "       timeouts: %u\n"
828                       "       avg_waittime: "LPU64" %s\n",
829                       cfs_atomic_read(&imp->imp_inflight),
830                       cfs_atomic_read(&imp->imp_unregistering),
831                       cfs_atomic_read(&imp->imp_timeouts),
832                       ret.lc_sum, ret.lc_units);
833
834         k = 0;
835         for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
836                 if (imp->imp_at.iat_portal[j] == 0)
837                         break;
838                 k = max_t(unsigned int, k,
839                           at_get(&imp->imp_at.iat_service_estimate[j]));
840         }
841         i += snprintf(page + i, count - i,
842                       "    service_estimates:\n"
843                       "       services: %u sec\n"
844                       "       network: %u sec\n",
845                       k,
846                       at_get(&imp->imp_at.iat_net_latency));
847
848         i += snprintf(page + i, count - i,
849                       "    transactions:\n"
850                       "       last_replay: "LPU64"\n"
851                       "       peer_committed: "LPU64"\n"
852                       "       last_checked: "LPU64"\n",
853                       imp->imp_last_replay_transno,
854                       imp->imp_peer_committed_transno,
855                       imp->imp_last_transno_checked);
856
857         /* avg data rates */
858         for (rw = 0; rw <= 1; rw++) {
859                 lprocfs_stats_collect(obd->obd_svc_stats,
860                                       PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
861                                       &ret);
862                 if (ret.lc_sum > 0) {
863                         do_div(ret.lc_sum, ret.lc_count);
864                         i += snprintf(page + i, count - i,
865                                       "    %s_data_averages:\n"
866                                       "       bytes_per_rpc: "LPU64"\n",
867                                       rw ? "write" : "read",
868                                       ret.lc_sum);
869                 }
870                 k = (int)ret.lc_sum;
871                 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
872                 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
873                 if (ret.lc_sum > 0) {
874                         do_div(ret.lc_sum, ret.lc_count);
875                         i += snprintf(page + i, count - i,
876                                       "       %s_per_rpc: "LPU64"\n",
877                                       ret.lc_units, ret.lc_sum);
878                         j = (int)ret.lc_sum;
879                         if (j > 0)
880                                 i += snprintf(page + i, count - i,
881                                               "       MB_per_sec: %u.%.02u\n",
882                                               k / j, (100 * k / j) % 100);
883                 }
884         }
885
886         LPROCFS_CLIMP_EXIT(obd);
887         return i;
888 }
889
890 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
891                       int *eof, void *data)
892 {
893         struct obd_device *obd = (struct obd_device *)data;
894         struct obd_import *imp;
895         int i, j, k;
896
897         LASSERT(obd != NULL);
898         LPROCFS_CLIMP_CHECK(obd);
899         imp = obd->u.cli.cl_import;
900         *eof = 1;
901
902         i = snprintf(page, count, "current_state: %s\n",
903                      ptlrpc_import_state_name(imp->imp_state));
904         i += snprintf(page + i, count - i,
905                       "state_history:\n");
906         k = imp->imp_state_hist_idx;
907         for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
908                 struct import_state_hist *ish =
909                         &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
910                 if (ish->ish_state == 0)
911                         continue;
912                 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
913                               ish->ish_time,
914                               ptlrpc_import_state_name(ish->ish_state));
915         }
916
917         LPROCFS_CLIMP_EXIT(obd);
918         return i;
919 }
920
921 int lprocfs_at_hist_helper(char *page, int count, int rc,
922                            struct adaptive_timeout *at)
923 {
924         int i;
925         for (i = 0; i < AT_BINS; i++)
926                 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
927         rc += snprintf(page + rc, count - rc, "\n");
928         return rc;
929 }
930
931 int lprocfs_rd_quota_resend_count(char *page, char **start, off_t off,
932                                   int count, int *eof, void *data)
933 {
934         struct obd_device *obd = data;
935
936         return snprintf(page, count, "%d\n",
937                         cfs_atomic_read(&obd->u.cli.cl_quota_resends));
938 }
939
940 int lprocfs_wr_quota_resend_count(struct file *file, const char *buffer,
941                                   unsigned long count, void *data)
942 {
943         struct obd_device *obd = data;
944         int val, rc;
945
946         rc = lprocfs_write_helper(buffer, count, &val);
947         if (rc)
948                 return rc;
949
950         cfs_atomic_set(&obd->u.cli.cl_quota_resends, val);
951
952         return count;
953 }
954
955 /* See also ptlrpc_lprocfs_rd_timeouts */
956 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
957                         int *eof, void *data)
958 {
959         struct obd_device *obd = (struct obd_device *)data;
960         struct obd_import *imp;
961         unsigned int cur, worst;
962         time_t now, worstt;
963         struct dhms ts;
964         int i, rc = 0;
965
966         LASSERT(obd != NULL);
967         LPROCFS_CLIMP_CHECK(obd);
968         imp = obd->u.cli.cl_import;
969         *eof = 1;
970
971         now = cfs_time_current_sec();
972
973         /* Some network health info for kicks */
974         s2dhms(&ts, now - imp->imp_last_reply_time);
975         rc += snprintf(page + rc, count - rc,
976                        "%-10s : %ld, "DHMS_FMT" ago\n",
977                        "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
978
979         cur = at_get(&imp->imp_at.iat_net_latency);
980         worst = imp->imp_at.iat_net_latency.at_worst_ever;
981         worstt = imp->imp_at.iat_net_latency.at_worst_time;
982         s2dhms(&ts, now - worstt);
983         rc += snprintf(page + rc, count - rc,
984                        "%-10s : cur %3u  worst %3u (at %ld, "DHMS_FMT" ago) ",
985                        "network", cur, worst, worstt, DHMS_VARS(&ts));
986         rc = lprocfs_at_hist_helper(page, count, rc,
987                                     &imp->imp_at.iat_net_latency);
988
989         for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
990                 if (imp->imp_at.iat_portal[i] == 0)
991                         break;
992                 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
993                 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
994                 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
995                 s2dhms(&ts, now - worstt);
996                 rc += snprintf(page + rc, count - rc,
997                                "portal %-2d  : cur %3u  worst %3u (at %ld, "
998                                DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
999                                cur, worst, worstt, DHMS_VARS(&ts));
1000                 rc = lprocfs_at_hist_helper(page, count, rc,
1001                                           &imp->imp_at.iat_service_estimate[i]);
1002         }
1003
1004         LPROCFS_CLIMP_EXIT(obd);
1005         return rc;
1006 }
1007
1008 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1009                              int count, int *eof, void *data)
1010 {
1011         struct obd_device *obd = data;
1012         __u64 flags;
1013         int ret = 0;
1014
1015         LPROCFS_CLIMP_CHECK(obd);
1016         flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1017         ret = snprintf(page, count, "flags="LPX64"\n", flags);
1018         ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1019         ret += snprintf(page + ret, count - ret, "\n");
1020         LPROCFS_CLIMP_EXIT(obd);
1021         return ret;
1022 }
1023 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1024
1025 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1026                            int *eof,  void *data)
1027 {
1028         struct obd_device *obd = data;
1029
1030         LASSERT(obd != NULL);
1031         *eof = 1;
1032         return snprintf(page, count, "%u\n", obd->obd_num_exports);
1033 }
1034
1035 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1036                        int *eof, void *data)
1037 {
1038         struct obd_type *class = (struct obd_type*) data;
1039
1040         LASSERT(class != NULL);
1041         *eof = 1;
1042         return snprintf(page, count, "%d\n", class->typ_refcnt);
1043 }
1044
1045 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1046 {
1047         int rc = 0;
1048
1049         LASSERT(obd != NULL);
1050         LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1051         LASSERT(obd->obd_type->typ_procroot != NULL);
1052
1053         obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1054                                                obd->obd_type->typ_procroot,
1055                                                list, obd);
1056         if (IS_ERR(obd->obd_proc_entry)) {
1057                 rc = PTR_ERR(obd->obd_proc_entry);
1058                 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1059                 obd->obd_proc_entry = NULL;
1060         }
1061         return rc;
1062 }
1063
1064 int lprocfs_obd_cleanup(struct obd_device *obd)
1065 {
1066         if (!obd)
1067                 return -EINVAL;
1068         if (obd->obd_proc_exports_entry) {
1069                 /* Should be no exports left */
1070                 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1071                 lprocfs_remove(&obd->obd_proc_exports_entry);
1072                 obd->obd_proc_exports_entry = NULL;
1073         }
1074         if (obd->obd_proc_entry) {
1075                 lprocfs_remove(&obd->obd_proc_entry);
1076                 obd->obd_proc_entry = NULL;
1077         }
1078         return 0;
1079 }
1080
1081 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1082 {
1083         CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1084                client_stat->nid_proc, client_stat->nid_stats,
1085                client_stat->nid_brw_stats);
1086
1087         LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1088                  "count %d\n",
1089                  cfs_atomic_read(&client_stat->nid_exp_ref_count));
1090
1091         cfs_hlist_del_init(&client_stat->nid_hash);
1092
1093         if (client_stat->nid_proc)
1094                 lprocfs_remove(&client_stat->nid_proc);
1095
1096         if (client_stat->nid_stats)
1097                 lprocfs_free_stats(&client_stat->nid_stats);
1098
1099         if (client_stat->nid_brw_stats)
1100                 OBD_FREE_PTR(client_stat->nid_brw_stats);
1101
1102         if (client_stat->nid_ldlm_stats)
1103                 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1104
1105         OBD_FREE_PTR(client_stat);
1106         return;
1107
1108 }
1109
1110 void lprocfs_free_per_client_stats(struct obd_device *obd)
1111 {
1112         struct nid_stat *stat;
1113         ENTRY;
1114
1115         /* we need extra list - because hash_exit called to early */
1116         /* not need locking because all clients is died */
1117         while(!cfs_list_empty(&obd->obd_nid_stats)) {
1118                 stat = cfs_list_entry(obd->obd_nid_stats.next,
1119                                       struct nid_stat, nid_list);
1120                 cfs_list_del_init(&stat->nid_list);
1121                 lprocfs_free_client_stats(stat);
1122         }
1123
1124         EXIT;
1125 }
1126
1127 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1128                                           enum lprocfs_stats_flags flags)
1129 {
1130         struct lprocfs_stats *stats;
1131         unsigned int percpusize;
1132         unsigned int i, j;
1133         unsigned int num_cpu;
1134
1135         if (num == 0)
1136                 return NULL;
1137
1138         if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1139                 num_cpu = 1;
1140         else
1141                 num_cpu = cfs_num_possible_cpus();
1142
1143         OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1144         if (stats == NULL)
1145                 return NULL;
1146
1147         if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1148                 stats->ls_flags = flags;
1149                 cfs_spin_lock_init(&stats->ls_lock);
1150                 /* Use this lock only if there are no percpu areas */
1151         } else {
1152                 stats->ls_flags = 0;
1153         }
1154
1155         percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1156         if (num_cpu > 1)
1157                 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1158
1159         for (i = 0; i < num_cpu; i++) {
1160                 OBD_ALLOC(stats->ls_percpu[i], percpusize);
1161                 if (stats->ls_percpu[i] == NULL) {
1162                         for (j = 0; j < i; j++) {
1163                                 OBD_FREE(stats->ls_percpu[j], percpusize);
1164                                 stats->ls_percpu[j] = NULL;
1165                         }
1166                         break;
1167                 }
1168         }
1169         if (stats->ls_percpu[0] == NULL) {
1170                 OBD_FREE(stats, offsetof(typeof(*stats),
1171                                          ls_percpu[num_cpu]));
1172                 return NULL;
1173         }
1174
1175         stats->ls_num = num;
1176         return stats;
1177 }
1178
1179 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1180 {
1181         struct lprocfs_stats *stats = *statsh;
1182         unsigned int num_cpu;
1183         unsigned int percpusize;
1184         unsigned int i;
1185
1186         if (stats == NULL || stats->ls_num == 0)
1187                 return;
1188         *statsh = NULL;
1189
1190         if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1191                 num_cpu = 1;
1192         else
1193                 num_cpu = cfs_num_possible_cpus();
1194
1195         percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1196         if (num_cpu > 1)
1197                 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1198         for (i = 0; i < num_cpu; i++)
1199                 OBD_FREE(stats->ls_percpu[i], percpusize);
1200         OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1201 }
1202
1203 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1204 {
1205         struct lprocfs_counter *percpu_cntr;
1206         int i,j;
1207         unsigned int num_cpu;
1208
1209         num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1210
1211         for (i = 0; i < num_cpu; i++) {
1212                 for (j = 0; j < stats->ls_num; j++) {
1213                         percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1214                         cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1215                         percpu_cntr->lc_count = 0;
1216                         percpu_cntr->lc_sum = 0;
1217                         percpu_cntr->lc_min = LC_MIN_INIT;
1218                         percpu_cntr->lc_max = 0;
1219                         percpu_cntr->lc_sumsquare = 0;
1220                         cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1221                 }
1222         }
1223
1224         lprocfs_stats_unlock(stats);
1225 }
1226
1227 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1228                                        size_t len, loff_t *off)
1229 {
1230         struct seq_file *seq = file->private_data;
1231         struct lprocfs_stats *stats = seq->private;
1232
1233         lprocfs_clear_stats(stats);
1234
1235         return len;
1236 }
1237
1238 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1239 {
1240         struct lprocfs_stats *stats = p->private;
1241         /* return 1st cpu location */
1242         return (*pos >= stats->ls_num) ? NULL :
1243                 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1244 }
1245
1246 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1247 {
1248 }
1249
1250 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1251 {
1252         struct lprocfs_stats *stats = p->private;
1253         ++*pos;
1254         return (*pos >= stats->ls_num) ? NULL :
1255                 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1256 }
1257
1258 /* seq file export of one lprocfs counter */
1259 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1260 {
1261        struct lprocfs_stats *stats = p->private;
1262        struct lprocfs_counter *cntr = v;
1263        struct lprocfs_counter ret;
1264        int idx, rc = 0;
1265
1266        if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1267                struct timeval now;
1268                cfs_gettimeofday(&now);
1269                rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1270                                "snapshot_time", now.tv_sec, now.tv_usec);
1271                if (rc < 0)
1272                        return rc;
1273        }
1274        idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1275
1276        lprocfs_stats_collect(stats, idx, &ret);
1277
1278        if (ret.lc_count == 0)
1279                goto out;
1280
1281        rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1282                        ret.lc_count, cntr->lc_units);
1283
1284        if (rc < 0)
1285                goto out;
1286
1287        if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1288                rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1289                                ret.lc_min, ret.lc_max, ret.lc_sum);
1290                if (rc < 0)
1291                        goto out;
1292                if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1293                        rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1294                if (rc < 0)
1295                        goto out;
1296        }
1297        rc = seq_printf(p, "\n");
1298  out:
1299        return (rc < 0) ? rc : 0;
1300 }
1301
1302 struct seq_operations lprocfs_stats_seq_sops = {
1303         start: lprocfs_stats_seq_start,
1304         stop:  lprocfs_stats_seq_stop,
1305         next:  lprocfs_stats_seq_next,
1306         show:  lprocfs_stats_seq_show,
1307 };
1308
1309 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1310 {
1311         struct proc_dir_entry *dp = PDE(inode);
1312         struct seq_file *seq;
1313         int rc;
1314
1315         if (LPROCFS_ENTRY_AND_CHECK(dp))
1316                 return -ENOENT;
1317
1318         rc = seq_open(file, &lprocfs_stats_seq_sops);
1319         if (rc) {
1320                 LPROCFS_EXIT();
1321                 return rc;
1322         }
1323         seq = file->private_data;
1324         seq->private = dp->data;
1325         return 0;
1326 }
1327
1328 struct file_operations lprocfs_stats_seq_fops = {
1329         .owner   = THIS_MODULE,
1330         .open    = lprocfs_stats_seq_open,
1331         .read    = seq_read,
1332         .write   = lprocfs_stats_seq_write,
1333         .llseek  = seq_lseek,
1334         .release = lprocfs_seq_release,
1335 };
1336
1337 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1338                            struct lprocfs_stats *stats)
1339 {
1340         struct proc_dir_entry *entry;
1341         LASSERT(root != NULL);
1342
1343         entry = create_proc_entry(name, 0644, root);
1344         if (entry == NULL)
1345                 return -ENOMEM;
1346         entry->proc_fops = &lprocfs_stats_seq_fops;
1347         entry->data = stats;
1348         return 0;
1349 }
1350
1351 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1352                           unsigned conf, const char *name, const char *units)
1353 {
1354         struct lprocfs_counter *c;
1355         int i;
1356         unsigned int num_cpu;
1357
1358         LASSERT(stats != NULL);
1359
1360         num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1361
1362         for (i = 0; i < num_cpu; i++) {
1363                 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1364                 c->lc_config = conf;
1365                 c->lc_count = 0;
1366                 c->lc_sum = 0;
1367                 c->lc_min = LC_MIN_INIT;
1368                 c->lc_max = 0;
1369                 c->lc_name = name;
1370                 c->lc_units = units;
1371         }
1372
1373         lprocfs_stats_unlock(stats);
1374 }
1375 EXPORT_SYMBOL(lprocfs_counter_init);
1376
1377 #define LPROCFS_OBD_OP_INIT(base, stats, op)                               \
1378 do {                                                                       \
1379         unsigned int coffset = base + OBD_COUNTER_OFFSET(op);              \
1380         LASSERT(coffset < stats->ls_num);                                  \
1381         lprocfs_counter_init(stats, coffset, 0, #op, "reqs");              \
1382 } while (0)
1383
1384 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1385 {
1386         LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1387         LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1388         LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1389         LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1390         LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1391         LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1392         LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1393         LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1394         LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1395         LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1396         LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1397         LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1398         LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1399         LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1400         LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1401         LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1402         LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1403         LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1404         LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1405         LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1406         LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1407         LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1408         LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1409         LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1410         LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1411         LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1412         LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1413         LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1414         LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1415         LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1416         LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1417         LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1418         LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1419         LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1420         LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1421         LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1422         LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1423         LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1424         LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1425         LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1426         LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1427         LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1428         LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1429         LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1430         LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1431         LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1432         LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1433         LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1434         LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1435         LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1436         LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1437         LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1438         LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1439         LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1440         LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1441         LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1442         LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1443         LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1444         LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1445         LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1446         LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1447         LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1448         LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1449         LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1450         LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1451         LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1452         LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1453         LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1454 }
1455
1456 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1457 {
1458         struct lprocfs_stats *stats;
1459         unsigned int num_stats;
1460         int rc, i;
1461
1462         LASSERT(obd->obd_stats == NULL);
1463         LASSERT(obd->obd_proc_entry != NULL);
1464         LASSERT(obd->obd_cntr_base == 0);
1465
1466         num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1467                 num_private_stats - 1 /* o_owner */;
1468         stats = lprocfs_alloc_stats(num_stats, 0);
1469         if (stats == NULL)
1470                 return -ENOMEM;
1471
1472         lprocfs_init_ops_stats(num_private_stats, stats);
1473
1474         for (i = num_private_stats; i < num_stats; i++) {
1475                 /* If this LBUGs, it is likely that an obd
1476                  * operation was added to struct obd_ops in
1477                  * <obd.h>, and that the corresponding line item
1478                  * LPROCFS_OBD_OP_INIT(.., .., opname)
1479                  * is missing from the list above. */
1480                 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1481                          "Missing obd_stat initializer obd_op "
1482                          "operation at offset %d.\n", i - num_private_stats);
1483         }
1484         rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1485         if (rc < 0) {
1486                 lprocfs_free_stats(&stats);
1487         } else {
1488                 obd->obd_stats  = stats;
1489                 obd->obd_cntr_base = num_private_stats;
1490         }
1491         return rc;
1492 }
1493
1494 void lprocfs_free_obd_stats(struct obd_device *obd)
1495 {
1496         if (obd->obd_stats)
1497                 lprocfs_free_stats(&obd->obd_stats);
1498 }
1499
1500 #define LPROCFS_MD_OP_INIT(base, stats, op)                             \
1501 do {                                                                    \
1502         unsigned int coffset = base + MD_COUNTER_OFFSET(op);            \
1503         LASSERT(coffset < stats->ls_num);                               \
1504         lprocfs_counter_init(stats, coffset, 0, #op, "reqs");           \
1505 } while (0)
1506
1507 int lprocfs_alloc_md_stats(struct obd_device *obd,
1508                            unsigned num_private_stats)
1509 {
1510         struct lprocfs_stats *stats;
1511         unsigned int num_stats;
1512         int rc, i;
1513
1514         LASSERT(obd->md_stats == NULL);
1515         LASSERT(obd->obd_proc_entry != NULL);
1516         LASSERT(obd->md_cntr_base == 0);
1517
1518         num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1519                     num_private_stats;
1520         stats = lprocfs_alloc_stats(num_stats, 0);
1521         if (stats == NULL)
1522                 return -ENOMEM;
1523
1524         LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1525         LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1526         LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1527         LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1528         LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1529         LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1530         LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1531         LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1532         LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1533         LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1534         LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1535         LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1536         LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1537         LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1538         LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1539         LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1540         LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1541         LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1542         LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1543         LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1544         LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1545         LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1546         LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1547         LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1548         LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1549         LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1550         LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1551         LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1552         LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1553         LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1554         LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1555
1556         for (i = num_private_stats; i < num_stats; i++) {
1557                 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1558                         CERROR("Missing md_stat initializer md_op "
1559                                "operation at offset %d. Aborting.\n",
1560                                i - num_private_stats);
1561                         LBUG();
1562                 }
1563         }
1564         rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1565         if (rc < 0) {
1566                 lprocfs_free_stats(&stats);
1567         } else {
1568                 obd->md_stats  = stats;
1569                 obd->md_cntr_base = num_private_stats;
1570         }
1571         return rc;
1572 }
1573
1574 void lprocfs_free_md_stats(struct obd_device *obd)
1575 {
1576         struct lprocfs_stats *stats = obd->md_stats;
1577
1578         if (stats != NULL) {
1579                 obd->md_stats = NULL;
1580                 obd->md_cntr_base = 0;
1581                 lprocfs_free_stats(&stats);
1582         }
1583 }
1584
1585 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1586 {
1587         lprocfs_counter_init(ldlm_stats,
1588                              LDLM_ENQUEUE - LDLM_FIRST_OPC,
1589                              0, "ldlm_enqueue", "reqs");
1590         lprocfs_counter_init(ldlm_stats,
1591                              LDLM_CONVERT - LDLM_FIRST_OPC,
1592                              0, "ldlm_convert", "reqs");
1593         lprocfs_counter_init(ldlm_stats,
1594                              LDLM_CANCEL - LDLM_FIRST_OPC,
1595                              0, "ldlm_cancel", "reqs");
1596         lprocfs_counter_init(ldlm_stats,
1597                              LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1598                              0, "ldlm_bl_callback", "reqs");
1599         lprocfs_counter_init(ldlm_stats,
1600                              LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1601                              0, "ldlm_cp_callback", "reqs");
1602         lprocfs_counter_init(ldlm_stats,
1603                              LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1604                              0, "ldlm_gl_callback", "reqs");
1605 }
1606
1607 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1608                          int *eof,  void *data)
1609 {
1610         struct obd_export *exp = data;
1611         LASSERT(exp != NULL);
1612         *eof = 1;
1613         return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1614 }
1615
1616 struct exp_uuid_cb_data {
1617         char                   *page;
1618         int                     count;
1619         int                    *eof;
1620         int                    *len;
1621 };
1622
1623 static void
1624 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1625                             int count, int *eof, int *len)
1626 {
1627         cb_data->page = page;
1628         cb_data->count = count;
1629         cb_data->eof = eof;
1630         cb_data->len = len;
1631 }
1632
1633 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1634 {
1635         struct obd_export *exp = (struct obd_export *)obj;
1636         struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1637
1638         if (exp->exp_nid_stats)
1639                 *data->len += snprintf((data->page + *data->len),
1640                                        data->count, "%s\n",
1641                                        obd_uuid2str(&exp->exp_client_uuid));
1642 }
1643
1644 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1645                         int *eof,  void *data)
1646 {
1647         struct nid_stat *stats = (struct nid_stat *)data;
1648         struct exp_uuid_cb_data cb_data;
1649         struct obd_device *obd = stats->nid_obd;
1650         int len = 0;
1651
1652         *eof = 1;
1653         page[0] = '\0';
1654         lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1655         cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1656                               lprocfs_exp_print_uuid, &cb_data);
1657         return (*cb_data.len);
1658 }
1659
1660 void lprocfs_exp_print_hash(void *obj, void *cb_data)
1661 {
1662         struct exp_uuid_cb_data *data = cb_data;
1663         struct obd_export       *exp = obj;
1664         cfs_hash_t              *hs;
1665
1666         hs = exp->exp_lock_hash;
1667         if (hs) {
1668                 if (!*data->len)
1669                         *data->len += cfs_hash_debug_header(data->page,
1670                                                             data->count);
1671
1672                 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1673                                                  data->count);
1674         }
1675 }
1676
1677 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1678                         int *eof,  void *data)
1679 {
1680         struct nid_stat *stats = (struct nid_stat *)data;
1681         struct exp_uuid_cb_data cb_data;
1682         struct obd_device *obd = stats->nid_obd;
1683         int len = 0;
1684
1685         *eof = 1;
1686         page[0] = '\0';
1687         lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1688
1689         cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1690                               lprocfs_exp_print_hash, &cb_data);
1691         return (*cb_data.len);
1692 }
1693
1694 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1695                                         int count, int *eof,  void *data)
1696 {
1697         *eof = 1;
1698         return snprintf(page, count, "%s\n",
1699                         "Write into this file to clear all nid stats and "
1700                         "stale nid entries");
1701 }
1702 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1703
1704 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1705 {
1706         struct nid_stat *stat = obj;
1707         int i;
1708         ENTRY;
1709         /* object has only hash + iterate_all references.
1710          * add/delete blocked by hash bucket lock */
1711         CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1712         if (cfs_atomic_read(&stat->nid_exp_ref_count) == 2) {
1713                 cfs_hlist_del_init(&stat->nid_hash);
1714                 nidstat_putref(stat);
1715                 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1716                 cfs_list_move(&stat->nid_list, data);
1717                 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
1718                 EXIT;
1719                 return;
1720         }
1721         /* we has reference to object - only clear data*/
1722         if (stat->nid_stats)
1723                 lprocfs_clear_stats(stat->nid_stats);
1724
1725         if (stat->nid_brw_stats) {
1726                 for (i = 0; i < BRW_LAST; i++)
1727                         lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1728         }
1729         EXIT;
1730         return;
1731 }
1732
1733 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1734                                          unsigned long count, void *data)
1735 {
1736         struct obd_device *obd = (struct obd_device *)data;
1737         struct nid_stat *client_stat;
1738         CFS_LIST_HEAD(free_list);
1739
1740         cfs_hash_for_each(obd->obd_nid_stats_hash,
1741                           lprocfs_nid_stats_clear_write_cb, &free_list);
1742
1743         while (!cfs_list_empty(&free_list)) {
1744                 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1745                                              nid_list);
1746                 cfs_list_del_init(&client_stat->nid_list);
1747                 lprocfs_free_client_stats(client_stat);
1748         }
1749
1750         return count;
1751 }
1752 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1753
1754 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1755 {
1756         struct nid_stat *new_stat, *old_stat;
1757         struct obd_device *obd = NULL;
1758         cfs_proc_dir_entry_t *entry;
1759         int rc = 0;
1760         ENTRY;
1761
1762         *newnid = 0;
1763
1764         if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1765             !exp->exp_obd->obd_nid_stats_hash)
1766                 RETURN(-EINVAL);
1767
1768         /* not test against zero because eric say:
1769          * You may only test nid against another nid, or LNET_NID_ANY.
1770          * Anything else is nonsense.*/
1771         if (!nid || *nid == LNET_NID_ANY)
1772                 RETURN(0);
1773
1774         obd = exp->exp_obd;
1775
1776         CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1777
1778         OBD_ALLOC_PTR(new_stat);
1779         if (new_stat == NULL)
1780                 RETURN(-ENOMEM);
1781
1782         new_stat->nid               = *nid;
1783         new_stat->nid_obd           = exp->exp_obd;
1784         cfs_atomic_set(&new_stat->nid_exp_ref_count, 0);
1785
1786         old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1787                                            nid, &new_stat->nid_hash);
1788         CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1789                old_stat, libcfs_nid2str(*nid),
1790                cfs_atomic_read(&new_stat->nid_exp_ref_count));
1791
1792         /* Return -EALREADY here so that we know that the /proc
1793          * entry already has been created */
1794         if (old_stat != new_stat) {
1795                 cfs_spin_lock(&obd->obd_nid_lock);
1796                 if (exp->exp_nid_stats != old_stat) {
1797                         if (exp->exp_nid_stats)
1798                                 nidstat_putref(exp->exp_nid_stats);
1799                         exp->exp_nid_stats = old_stat;
1800                 } else {
1801                         /* cfs_hash_findadd_unique() has added
1802                          * old_stat's refcount */
1803                         nidstat_putref(old_stat);
1804                 }
1805
1806                 cfs_spin_unlock(&obd->obd_nid_lock);
1807
1808                 GOTO(destroy_new, rc = -EALREADY);
1809         }
1810         /* not found - create */
1811         new_stat->nid_proc = lprocfs_register(libcfs_nid2str(*nid),
1812                                               obd->obd_proc_exports_entry,
1813                                               NULL, NULL);
1814         if (new_stat->nid_proc == NULL) {
1815                 CERROR("Error making export directory for nid %s\n",
1816                        libcfs_nid2str(*nid));
1817                 GOTO(destroy_new_ns, rc = -ENOMEM);
1818         }
1819
1820         entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1821                                    lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1822         if (IS_ERR(entry)) {
1823                 CWARN("Error adding the NID stats file\n");
1824                 rc = PTR_ERR(entry);
1825                 GOTO(destroy_new_ns, rc);
1826         }
1827
1828         entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1829                                    lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1830         if (IS_ERR(entry)) {
1831                 CWARN("Error adding the hash file\n");
1832                 rc = PTR_ERR(entry);
1833                 GOTO(destroy_new_ns, rc);
1834         }
1835
1836         if (exp->exp_nid_stats)
1837                 nidstat_putref(exp->exp_nid_stats);
1838         nidstat_getref(new_stat);
1839         exp->exp_nid_stats = new_stat;
1840         *newnid = 1;
1841         /* protect competitive add to list, not need locking on destroy */
1842         cfs_spin_lock(&obd->obd_nid_lock);
1843         cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1844         cfs_spin_unlock(&obd->obd_nid_lock);
1845
1846         RETURN(rc);
1847
1848 destroy_new_ns:
1849         if (new_stat->nid_proc != NULL)
1850                 lprocfs_remove(&new_stat->nid_proc);
1851         cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1852
1853 destroy_new:
1854         OBD_FREE_PTR(new_stat);
1855         RETURN(rc);
1856 }
1857
1858 int lprocfs_exp_cleanup(struct obd_export *exp)
1859 {
1860         struct nid_stat *stat = exp->exp_nid_stats;
1861
1862         if(!stat || !exp->exp_obd)
1863                 RETURN(0);
1864
1865         nidstat_putref(exp->exp_nid_stats);
1866         exp->exp_nid_stats = NULL;
1867
1868         return 0;
1869 }
1870
1871 int lprocfs_write_helper(const char *buffer, unsigned long count,
1872                          int *val)
1873 {
1874         return lprocfs_write_frac_helper(buffer, count, val, 1);
1875 }
1876
1877 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1878                               int *val, int mult)
1879 {
1880         char kernbuf[20], *end, *pbuf;
1881
1882         if (count > (sizeof(kernbuf) - 1))
1883                 return -EINVAL;
1884
1885         if (cfs_copy_from_user(kernbuf, buffer, count))
1886                 return -EFAULT;
1887
1888         kernbuf[count] = '\0';
1889         pbuf = kernbuf;
1890         if (*pbuf == '-') {
1891                 mult = -mult;
1892                 pbuf++;
1893         }
1894
1895         *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1896         if (pbuf == end)
1897                 return -EINVAL;
1898
1899         if (end != NULL && *end == '.') {
1900                 int temp_val, pow = 1;
1901                 int i;
1902
1903                 pbuf = end + 1;
1904                 if (strlen(pbuf) > 5)
1905                         pbuf[5] = '\0'; /*only allow 5bits fractional*/
1906
1907                 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1908
1909                 if (pbuf < end) {
1910                         for (i = 0; i < (end - pbuf); i++)
1911                                 pow *= 10;
1912
1913                         *val += temp_val / pow;
1914                 }
1915         }
1916         return 0;
1917 }
1918
1919 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
1920                              int mult)
1921 {
1922         long decimal_val, frac_val;
1923         int prtn;
1924
1925         if (count < 10)
1926                 return -EINVAL;
1927
1928         decimal_val = val / mult;
1929         prtn = snprintf(buffer, count, "%ld", decimal_val);
1930         frac_val = val % mult;
1931
1932         if (prtn < (count - 4) && frac_val > 0) {
1933                 long temp_frac;
1934                 int i, temp_mult = 1, frac_bits = 0;
1935
1936                 temp_frac = frac_val * 10;
1937                 buffer[prtn++] = '.';
1938                 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
1939                         /* only reserved 2 bits fraction */
1940                         buffer[prtn++] ='0';
1941                         temp_frac *= 10;
1942                         frac_bits++;
1943                 }
1944                 /*
1945                  * Need to think these cases :
1946                  *      1. #echo x.00 > /proc/xxx       output result : x
1947                  *      2. #echo x.0x > /proc/xxx       output result : x.0x
1948                  *      3. #echo x.x0 > /proc/xxx       output result : x.x
1949                  *      4. #echo x.xx > /proc/xxx       output result : x.xx
1950                  *      Only reserved 2 bits fraction.
1951                  */
1952                 for (i = 0; i < (5 - prtn); i++)
1953                         temp_mult *= 10;
1954
1955                 frac_bits = min((int)count - prtn, 3 - frac_bits);
1956                 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
1957                                  frac_val * temp_mult / mult);
1958
1959                 prtn--;
1960                 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1961                         prtn--;
1962                         if (buffer[prtn] == '.') {
1963                                 prtn--;
1964                                 break;
1965                         }
1966                 }
1967                 prtn++;
1968         }
1969         buffer[prtn++] ='\n';
1970         return prtn;
1971 }
1972
1973 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1974 {
1975         return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1976 }
1977
1978 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1979                               __u64 *val, int mult)
1980 {
1981         char kernbuf[22], *end, *pbuf;
1982         __u64 whole, frac = 0, units;
1983         unsigned frac_d = 1;
1984
1985         if (count > (sizeof(kernbuf) - 1))
1986                 return -EINVAL;
1987
1988         if (cfs_copy_from_user(kernbuf, buffer, count))
1989                 return -EFAULT;
1990
1991         kernbuf[count] = '\0';
1992         pbuf = kernbuf;
1993         if (*pbuf == '-') {
1994                 mult = -mult;
1995                 pbuf++;
1996         }
1997
1998         whole = simple_strtoull(pbuf, &end, 10);
1999         if (pbuf == end)
2000                 return -EINVAL;
2001
2002         if (end != NULL && *end == '.') {
2003                 int i;
2004                 pbuf = end + 1;
2005
2006                 /* need to limit frac_d to a __u32 */
2007                 if (strlen(pbuf) > 10)
2008                         pbuf[10] = '\0';
2009
2010                 frac = simple_strtoull(pbuf, &end, 10);
2011                 /* count decimal places */
2012                 for (i = 0; i < (end - pbuf); i++)
2013                         frac_d *= 10;
2014         }
2015
2016         units = 1;
2017         switch(*end) {
2018         case 'p': case 'P':
2019                 units <<= 10;
2020         case 't': case 'T':
2021                 units <<= 10;
2022         case 'g': case 'G':
2023                 units <<= 10;
2024         case 'm': case 'M':
2025                 units <<= 10;
2026         case 'k': case 'K':
2027                 units <<= 10;
2028         }
2029         /* Specified units override the multiplier */
2030         if (units)
2031                 mult = mult < 0 ? -units : units;
2032
2033         frac *= mult;
2034         do_div(frac, frac_d);
2035         *val = whole * mult + frac;
2036         return 0;
2037 }
2038
2039 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2040                        struct file_operations *seq_fops, void *data)
2041 {
2042         struct proc_dir_entry *entry;
2043         ENTRY;
2044
2045         entry = create_proc_entry(name, mode, parent);
2046         if (entry == NULL)
2047                 RETURN(-ENOMEM);
2048         entry->proc_fops = seq_fops;
2049         entry->data = data;
2050
2051         RETURN(0);
2052 }
2053 EXPORT_SYMBOL(lprocfs_seq_create);
2054
2055 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2056                                       mode_t mode,
2057                                       struct file_operations *seq_fops,
2058                                       void *data)
2059 {
2060         return (lprocfs_seq_create(dev->obd_proc_entry, name,
2061                                    mode, seq_fops, data));
2062 }
2063 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2064
2065 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2066 {
2067         if (value >= OBD_HIST_MAX)
2068                 value = OBD_HIST_MAX - 1;
2069
2070         cfs_spin_lock(&oh->oh_lock);
2071         oh->oh_buckets[value]++;
2072         cfs_spin_unlock(&oh->oh_lock);
2073 }
2074 EXPORT_SYMBOL(lprocfs_oh_tally);
2075
2076 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2077 {
2078         unsigned int val;
2079
2080         for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2081                 ;
2082
2083         lprocfs_oh_tally(oh, val);
2084 }
2085 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2086
2087 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2088 {
2089         unsigned long ret = 0;
2090         int i;
2091
2092         for (i = 0; i < OBD_HIST_MAX; i++)
2093                 ret +=  oh->oh_buckets[i];
2094         return ret;
2095 }
2096 EXPORT_SYMBOL(lprocfs_oh_sum);
2097
2098 void lprocfs_oh_clear(struct obd_histogram *oh)
2099 {
2100         cfs_spin_lock(&oh->oh_lock);
2101         memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2102         cfs_spin_unlock(&oh->oh_lock);
2103 }
2104 EXPORT_SYMBOL(lprocfs_oh_clear);
2105
2106 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2107                         int count, int *eof, void *data)
2108 {
2109         struct obd_device *obd = data;
2110         int c = 0;
2111
2112         if (obd == NULL)
2113                 return 0;
2114
2115         c += cfs_hash_debug_header(page, count);
2116         c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2117         c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2118         c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2119
2120         return c;
2121 }
2122 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2123
2124 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2125                                    int count, int *eof, void *data)
2126 {
2127         struct obd_device *obd = data;
2128         int len = 0, size;
2129
2130         LASSERT(obd != NULL);
2131         LASSERT(count >= 0);
2132
2133         /* Set start of user data returned to
2134            page + off since the user may have
2135            requested to read much smaller than
2136            what we need to read */
2137         *start = page + off;
2138
2139         /* We know we are allocated a page here.
2140            Also we know that this function will
2141            not need to write more than a page
2142            so we can truncate at CFS_PAGE_SIZE.  */
2143         size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2144
2145         /* Initialize the page */
2146         memset(page, 0, size);
2147
2148         if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2149                 goto out;
2150         if (obd->obd_max_recoverable_clients == 0) {
2151                 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2152                         goto out;
2153
2154                 goto fclose;
2155         }
2156
2157         /* sampled unlocked, but really... */
2158         if (obd->obd_recovering == 0) {
2159                 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2160                         goto out;
2161                 if (lprocfs_obd_snprintf(&page, size, &len,
2162                                          "recovery_start: %lu\n",
2163                                          obd->obd_recovery_start) <= 0)
2164                         goto out;
2165                 if (lprocfs_obd_snprintf(&page, size, &len,
2166                                          "recovery_duration: %lu\n",
2167                                          obd->obd_recovery_end -
2168                                          obd->obd_recovery_start) <= 0)
2169                         goto out;
2170                 /* Number of clients that have completed recovery */
2171                 if (lprocfs_obd_snprintf(&page, size, &len,
2172                                          "completed_clients: %d/%d\n",
2173                                          obd->obd_max_recoverable_clients -
2174                                          obd->obd_stale_clients,
2175                                          obd->obd_max_recoverable_clients) <= 0)
2176                         goto out;
2177                 if (lprocfs_obd_snprintf(&page, size, &len,
2178                                          "replayed_requests: %d\n",
2179                                          obd->obd_replayed_requests) <= 0)
2180                         goto out;
2181                 if (lprocfs_obd_snprintf(&page, size, &len,
2182                                          "last_transno: "LPD64"\n",
2183                                          obd->obd_next_recovery_transno - 1)<=0)
2184                         goto out;
2185                 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2186                                          obd->obd_version_recov ? "ON" : "OFF")<=0)
2187                         goto out;
2188                 goto fclose;
2189         }
2190
2191         if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2192                 goto out;
2193         if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2194                                  obd->obd_recovery_start) <= 0)
2195                 goto out;
2196         if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2197                            cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2198                            obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2199                 goto out;
2200         if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2201                                  obd->obd_connected_clients,
2202                                  obd->obd_max_recoverable_clients) <= 0)
2203                 goto out;
2204         /* Number of clients that have completed recovery */
2205         if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2206                                  cfs_atomic_read(&obd->obd_req_replay_clients))
2207                 <= 0)
2208                 goto out;
2209         if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2210                                  cfs_atomic_read(&obd->obd_lock_replay_clients))
2211                 <=0)
2212                 goto out;
2213         if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2214                                  obd->obd_connected_clients -
2215                                  cfs_atomic_read(&obd->obd_lock_replay_clients))
2216                 <=0)
2217                 goto out;
2218         if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2219                                  obd->obd_stale_clients) <= 0)
2220                 goto out;
2221         if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2222                                  obd->obd_replayed_requests) <= 0)
2223                 goto out;
2224         if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2225                                  obd->obd_requests_queued_for_recovery) <= 0)
2226                 goto out;
2227
2228         if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2229                                  obd->obd_next_recovery_transno) <= 0)
2230                 goto out;
2231
2232 fclose:
2233         *eof = 1;
2234 out:
2235         return min(count, len - (int)off);
2236 }
2237 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2238
2239 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
2240                                     int count, int *eof, void *data)
2241 {
2242         struct obd_device *obd = data;
2243         LASSERT(obd != NULL);
2244
2245         return snprintf(page, count, "%lu\n", obd->obd_recovery_max_time);
2246 }
2247 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
2248
2249 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
2250                                     unsigned long count, void *data)
2251 {
2252         struct obd_device *obd = data;
2253         int val, rc;
2254         LASSERT(obd != NULL);
2255
2256         rc = lprocfs_write_helper(buffer, count, &val);
2257         if (rc)
2258                 return rc;
2259
2260         obd->obd_recovery_max_time = val;
2261         return count;
2262 }
2263 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
2264
2265
2266 EXPORT_SYMBOL(lprocfs_register);
2267 EXPORT_SYMBOL(lprocfs_srch);
2268 EXPORT_SYMBOL(lprocfs_remove);
2269 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2270 EXPORT_SYMBOL(lprocfs_add_vars);
2271 EXPORT_SYMBOL(lprocfs_obd_setup);
2272 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2273 EXPORT_SYMBOL(lprocfs_add_simple);
2274 EXPORT_SYMBOL(lprocfs_add_symlink);
2275 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2276 EXPORT_SYMBOL(lprocfs_alloc_stats);
2277 EXPORT_SYMBOL(lprocfs_free_stats);
2278 EXPORT_SYMBOL(lprocfs_clear_stats);
2279 EXPORT_SYMBOL(lprocfs_register_stats);
2280 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2281 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2282 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2283 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2284 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2285 EXPORT_SYMBOL(lprocfs_free_md_stats);
2286 EXPORT_SYMBOL(lprocfs_exp_setup);
2287 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2288
2289 EXPORT_SYMBOL(lprocfs_rd_u64);
2290 EXPORT_SYMBOL(lprocfs_rd_atomic);
2291 EXPORT_SYMBOL(lprocfs_wr_atomic);
2292 EXPORT_SYMBOL(lprocfs_rd_uint);
2293 EXPORT_SYMBOL(lprocfs_wr_uint);
2294 EXPORT_SYMBOL(lprocfs_rd_uuid);
2295 EXPORT_SYMBOL(lprocfs_rd_name);
2296 EXPORT_SYMBOL(lprocfs_rd_fstype);
2297 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2298 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2299 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2300 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2301 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2302 EXPORT_SYMBOL(lprocfs_rd_import);
2303 EXPORT_SYMBOL(lprocfs_rd_state);
2304 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2305 EXPORT_SYMBOL(lprocfs_rd_blksize);
2306 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2307 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2308 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2309 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2310 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2311 EXPORT_SYMBOL(lprocfs_rd_quota_resend_count);
2312 EXPORT_SYMBOL(lprocfs_wr_quota_resend_count);
2313
2314 EXPORT_SYMBOL(lprocfs_write_helper);
2315 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2316 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2317 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2318 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2319 EXPORT_SYMBOL(lprocfs_stats_collect);
2320 #endif /* LPROCFS*/