staging/lustre/obd: remove unused lprocfs_exp_setup() and related functions
[firefly-linux-kernel-4.4.55.git] / drivers / staging / lustre / lustre / obdclass / lprocfs_status.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2011, 2012, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/obdclass/lprocfs_status.c
37  *
38  * Author: Hariharan Thantry <thantry@users.sourceforge.net>
39  */
40
41 #define DEBUG_SUBSYSTEM S_CLASS
42
43
44 #include "../include/obd_class.h"
45 #include "../include/lprocfs_status.h"
46 #include "../include/lustre/lustre_idl.h"
47 #include <linux/seq_file.h>
48 #include <linux/ctype.h>
49
50 static const char * const obd_connect_names[] = {
51         "read_only",
52         "lov_index",
53         "unused",
54         "write_grant",
55         "server_lock",
56         "version",
57         "request_portal",
58         "acl",
59         "xattr",
60         "create_on_write",
61         "truncate_lock",
62         "initial_transno",
63         "inode_bit_locks",
64         "join_file(obsolete)",
65         "getattr_by_fid",
66         "no_oh_for_devices",
67         "remote_client",
68         "remote_client_by_force",
69         "max_byte_per_rpc",
70         "64bit_qdata",
71         "mds_capability",
72         "oss_capability",
73         "early_lock_cancel",
74         "som",
75         "adaptive_timeouts",
76         "lru_resize",
77         "mds_mds_connection",
78         "real_conn",
79         "change_qunit_size",
80         "alt_checksum_algorithm",
81         "fid_is_enabled",
82         "version_recovery",
83         "pools",
84         "grant_shrink",
85         "skip_orphan",
86         "large_ea",
87         "full20",
88         "layout_lock",
89         "64bithash",
90         "object_max_bytes",
91         "imp_recov",
92         "jobstats",
93         "umask",
94         "einprogress",
95         "grant_param",
96         "flock_owner",
97         "lvb_type",
98         "nanoseconds_times",
99         "lightweight_conn",
100         "short_io",
101         "pingless",
102         "flock_deadlock",
103         "disp_stripe",
104         "unknown",
105         NULL
106 };
107
108 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
109 {
110         __u64 mask = 1;
111         int i, ret = 0;
112
113         for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
114                 if (flags & mask)
115                         ret += snprintf(page + ret, count - ret, "%s%s",
116                                         ret ? sep : "", obd_connect_names[i]);
117         }
118         if (flags & ~(mask - 1))
119                 ret += snprintf(page + ret, count - ret,
120                                 "%sunknown flags %#llx",
121                                 ret ? sep : "", flags & ~(mask - 1));
122         return ret;
123 }
124 EXPORT_SYMBOL(obd_connect_flags2str);
125
126 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
127                              int mult)
128 {
129         long decimal_val, frac_val;
130         int prtn;
131
132         if (count < 10)
133                 return -EINVAL;
134
135         decimal_val = val / mult;
136         prtn = snprintf(buffer, count, "%ld", decimal_val);
137         frac_val = val % mult;
138
139         if (prtn < (count - 4) && frac_val > 0) {
140                 long temp_frac;
141                 int i, temp_mult = 1, frac_bits = 0;
142
143                 temp_frac = frac_val * 10;
144                 buffer[prtn++] = '.';
145                 while (frac_bits < 2 && (temp_frac / mult) < 1) {
146                         /* only reserved 2 bits fraction */
147                         buffer[prtn++] = '0';
148                         temp_frac *= 10;
149                         frac_bits++;
150                 }
151                 /*
152                  * Need to think these cases :
153                  *      1. #echo x.00 > /proc/xxx       output result : x
154                  *      2. #echo x.0x > /proc/xxx       output result : x.0x
155                  *      3. #echo x.x0 > /proc/xxx       output result : x.x
156                  *      4. #echo x.xx > /proc/xxx       output result : x.xx
157                  *      Only reserved 2 bits fraction.
158                  */
159                 for (i = 0; i < (5 - prtn); i++)
160                         temp_mult *= 10;
161
162                 frac_bits = min((int)count - prtn, 3 - frac_bits);
163                 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
164                                  frac_val * temp_mult / mult);
165
166                 prtn--;
167                 while (buffer[prtn] < '1' || buffer[prtn] > '9') {
168                         prtn--;
169                         if (buffer[prtn] == '.') {
170                                 prtn--;
171                                 break;
172                         }
173                 }
174                 prtn++;
175         }
176         buffer[prtn++] = '\n';
177         return prtn;
178 }
179 EXPORT_SYMBOL(lprocfs_read_frac_helper);
180
181 int lprocfs_write_frac_helper(const char __user *buffer, unsigned long count,
182                               int *val, int mult)
183 {
184         char kernbuf[20], *end, *pbuf;
185
186         if (count > (sizeof(kernbuf) - 1))
187                 return -EINVAL;
188
189         if (copy_from_user(kernbuf, buffer, count))
190                 return -EFAULT;
191
192         kernbuf[count] = '\0';
193         pbuf = kernbuf;
194         if (*pbuf == '-') {
195                 mult = -mult;
196                 pbuf++;
197         }
198
199         *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
200         if (pbuf == end)
201                 return -EINVAL;
202
203         if (end != NULL && *end == '.') {
204                 int temp_val, pow = 1;
205                 int i;
206
207                 pbuf = end + 1;
208                 if (strlen(pbuf) > 5)
209                         pbuf[5] = '\0'; /*only allow 5bits fractional*/
210
211                 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
212
213                 if (pbuf < end) {
214                         for (i = 0; i < (end - pbuf); i++)
215                                 pow *= 10;
216
217                         *val += temp_val / pow;
218                 }
219         }
220         return 0;
221 }
222 EXPORT_SYMBOL(lprocfs_write_frac_helper);
223
224 #if defined (CONFIG_PROC_FS)
225
226 static int lprocfs_no_percpu_stats;
227 module_param(lprocfs_no_percpu_stats, int, 0644);
228 MODULE_PARM_DESC(lprocfs_no_percpu_stats, "Do not alloc percpu data for lprocfs stats");
229
230 #define MAX_STRING_SIZE 128
231
232 int lprocfs_single_release(struct inode *inode, struct file *file)
233 {
234         return single_release(inode, file);
235 }
236 EXPORT_SYMBOL(lprocfs_single_release);
237
238 int lprocfs_seq_release(struct inode *inode, struct file *file)
239 {
240         return seq_release(inode, file);
241 }
242 EXPORT_SYMBOL(lprocfs_seq_release);
243
244 /* lprocfs API calls */
245
246 struct dentry *ldebugfs_add_simple(struct dentry *root,
247                                    char *name, void *data,
248                                    struct file_operations *fops)
249 {
250         struct dentry *entry;
251         umode_t mode = 0;
252
253         if (root == NULL || name == NULL || fops == NULL)
254                 return ERR_PTR(-EINVAL);
255
256         if (fops->read)
257                 mode = 0444;
258         if (fops->write)
259                 mode |= 0200;
260         entry = debugfs_create_file(name, mode, root, data, fops);
261         if (IS_ERR_OR_NULL(entry)) {
262                 CERROR("LprocFS: No memory to create <debugfs> entry %s", name);
263                 return entry ?: ERR_PTR(-ENOMEM);
264         }
265         return entry;
266 }
267 EXPORT_SYMBOL(ldebugfs_add_simple);
268
269 struct proc_dir_entry *lprocfs_add_simple(struct proc_dir_entry *root,
270                                      char *name, void *data,
271                                      struct file_operations *fops)
272 {
273         struct proc_dir_entry *proc;
274         umode_t mode = 0;
275
276         if (root == NULL || name == NULL || fops == NULL)
277                 return ERR_PTR(-EINVAL);
278
279         if (fops->read)
280                 mode = 0444;
281         if (fops->write)
282                 mode |= 0200;
283         proc = proc_create_data(name, mode, root, fops, data);
284         if (!proc) {
285                 CERROR("LprocFS: No memory to create /proc entry %s", name);
286                 return ERR_PTR(-ENOMEM);
287         }
288         return proc;
289 }
290 EXPORT_SYMBOL(lprocfs_add_simple);
291
292 struct dentry *ldebugfs_add_symlink(const char *name, struct dentry *parent,
293                                     const char *format, ...)
294 {
295         struct dentry *entry;
296         char *dest;
297         va_list ap;
298
299         if (parent == NULL || format == NULL)
300                 return NULL;
301
302         dest = kzalloc(MAX_STRING_SIZE + 1, GFP_KERNEL);
303         if (dest == NULL)
304                 return NULL;
305
306         va_start(ap, format);
307         vsnprintf(dest, MAX_STRING_SIZE, format, ap);
308         va_end(ap);
309
310         entry = debugfs_create_symlink(name, parent, dest);
311         if (IS_ERR_OR_NULL(entry)) {
312                 CERROR("LdebugFS: Could not create symbolic link from %s to %s",
313                         name, dest);
314                 entry = NULL;
315         }
316
317         kfree(dest);
318         return entry;
319 }
320 EXPORT_SYMBOL(ldebugfs_add_symlink);
321
322 static struct file_operations lprocfs_generic_fops = { };
323
324 int ldebugfs_add_vars(struct dentry *parent,
325                       struct lprocfs_vars *list,
326                       void *data)
327 {
328         if (IS_ERR_OR_NULL(parent) || IS_ERR_OR_NULL(list))
329                 return -EINVAL;
330
331         while (list->name != NULL) {
332                 struct dentry *entry;
333                 umode_t mode = 0;
334
335                 if (list->proc_mode != 0000) {
336                         mode = list->proc_mode;
337                 } else if (list->fops) {
338                         if (list->fops->read)
339                                 mode = 0444;
340                         if (list->fops->write)
341                                 mode |= 0200;
342                 }
343                 entry = debugfs_create_file(list->name, mode, parent,
344                                             list->data ?: data,
345                                             list->fops ?: &lprocfs_generic_fops
346                                            );
347                 if (IS_ERR_OR_NULL(entry))
348                         return entry ? PTR_ERR(entry) : -ENOMEM;
349                 list++;
350         }
351         return 0;
352 }
353 EXPORT_SYMBOL(ldebugfs_add_vars);
354
355 /**
356  * Add /proc entries.
357  *
358  * \param root [in]  The parent proc entry on which new entry will be added.
359  * \param list [in]  Array of proc entries to be added.
360  * \param data [in]  The argument to be passed when entries read/write routines
361  *                 are called through /proc file.
362  *
363  * \retval 0   on success
364  *       < 0 on error
365  */
366 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
367                      void *data)
368 {
369         if (root == NULL || list == NULL)
370                 return -EINVAL;
371
372         while (list->name != NULL) {
373                 struct proc_dir_entry *proc;
374                 umode_t mode = 0;
375
376                 if (list->proc_mode != 0000) {
377                         mode = list->proc_mode;
378                 } else if (list->fops) {
379                         if (list->fops->read)
380                                 mode = 0444;
381                         if (list->fops->write)
382                                 mode |= 0200;
383                 }
384                 proc = proc_create_data(list->name, mode, root,
385                                         list->fops ?: &lprocfs_generic_fops,
386                                         list->data ?: data);
387                 if (proc == NULL)
388                         return -ENOMEM;
389                 list++;
390         }
391         return 0;
392 }
393 EXPORT_SYMBOL(lprocfs_add_vars);
394
395 void ldebugfs_remove(struct dentry **entryp)
396 {
397         debugfs_remove(*entryp);
398         *entryp = NULL;
399 }
400 EXPORT_SYMBOL(ldebugfs_remove);
401
402 void lprocfs_remove(struct proc_dir_entry **rooth)
403 {
404         proc_remove(*rooth);
405         *rooth = NULL;
406 }
407 EXPORT_SYMBOL(lprocfs_remove);
408
409 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
410 {
411         LASSERT(parent != NULL);
412         remove_proc_entry(name, parent);
413 }
414 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
415
416 struct dentry *ldebugfs_register(const char *name,
417                                  struct dentry *parent,
418                                  struct lprocfs_vars *list, void *data)
419 {
420         struct dentry *entry;
421
422         entry = debugfs_create_dir(name, parent);
423         if (IS_ERR_OR_NULL(entry)) {
424                 entry = entry ?: ERR_PTR(-ENOMEM);
425                 goto out;
426         }
427
428         if (!IS_ERR_OR_NULL(list)) {
429                 int rc;
430
431                 rc = ldebugfs_add_vars(entry, list, data);
432                 if (rc != 0) {
433                         debugfs_remove(entry);
434                         entry = ERR_PTR(rc);
435                 }
436         }
437 out:
438         return entry;
439 }
440 EXPORT_SYMBOL(ldebugfs_register);
441
442 struct proc_dir_entry *lprocfs_register(const char *name,
443                                         struct proc_dir_entry *parent,
444                                         struct lprocfs_vars *list, void *data)
445 {
446         struct proc_dir_entry *entry;
447
448         entry = proc_mkdir(name, parent);
449         if (entry == NULL) {
450                 entry = ERR_PTR(-ENOMEM);
451                 goto out;
452         }
453
454         if (list != NULL) {
455                 int rc = lprocfs_add_vars(entry, list, data);
456                 if (rc != 0) {
457                         lprocfs_remove(&entry);
458                         entry = ERR_PTR(rc);
459                 }
460         }
461 out:
462         return entry;
463 }
464 EXPORT_SYMBOL(lprocfs_register);
465
466 /* Generic callbacks */
467 int lprocfs_rd_uint(struct seq_file *m, void *data)
468 {
469         seq_printf(m, "%u\n", *(unsigned int *)data);
470         return 0;
471 }
472 EXPORT_SYMBOL(lprocfs_rd_uint);
473
474 int lprocfs_wr_uint(struct file *file, const char __user *buffer,
475                     unsigned long count, void *data)
476 {
477         unsigned *p = data;
478         char dummy[MAX_STRING_SIZE + 1], *end;
479         unsigned long tmp;
480
481         dummy[MAX_STRING_SIZE] = '\0';
482         if (copy_from_user(dummy, buffer, MAX_STRING_SIZE))
483                 return -EFAULT;
484
485         tmp = simple_strtoul(dummy, &end, 0);
486         if (dummy == end)
487                 return -EINVAL;
488
489         *p = (unsigned int)tmp;
490         return count;
491 }
492 EXPORT_SYMBOL(lprocfs_wr_uint);
493
494 int lprocfs_rd_u64(struct seq_file *m, void *data)
495 {
496         seq_printf(m, "%llu\n", *(__u64 *)data);
497         return 0;
498 }
499 EXPORT_SYMBOL(lprocfs_rd_u64);
500
501 int lprocfs_rd_atomic(struct seq_file *m, void *data)
502 {
503         atomic_t *atom = data;
504         LASSERT(atom != NULL);
505         seq_printf(m, "%d\n", atomic_read(atom));
506         return 0;
507 }
508 EXPORT_SYMBOL(lprocfs_rd_atomic);
509
510 int lprocfs_wr_atomic(struct file *file, const char __user *buffer,
511                       unsigned long count, void *data)
512 {
513         atomic_t *atm = data;
514         int val = 0;
515         int rc;
516
517         rc = lprocfs_write_helper(buffer, count, &val);
518         if (rc < 0)
519                 return rc;
520
521         if (val <= 0)
522                 return -ERANGE;
523
524         atomic_set(atm, val);
525         return count;
526 }
527 EXPORT_SYMBOL(lprocfs_wr_atomic);
528
529 static ssize_t uuid_show(struct kobject *kobj, struct attribute *attr,
530                          char *buf)
531 {
532         struct obd_device *obd = container_of(kobj, struct obd_device,
533                                               obd_kobj);
534
535         return sprintf(buf, "%s\n", obd->obd_uuid.uuid);
536 }
537 LUSTRE_RO_ATTR(uuid);
538
539 int lprocfs_rd_name(struct seq_file *m, void *data)
540 {
541         struct obd_device *dev = data;
542
543         LASSERT(dev != NULL);
544         seq_printf(m, "%s\n", dev->obd_name);
545         return 0;
546 }
547 EXPORT_SYMBOL(lprocfs_rd_name);
548
549 static ssize_t blocksize_show(struct kobject *kobj, struct attribute *attr,
550                               char *buf)
551 {
552         struct obd_device *obd = container_of(kobj, struct obd_device,
553                                               obd_kobj);
554         struct obd_statfs  osfs;
555         int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
556                             cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
557                             OBD_STATFS_NODELAY);
558         if (!rc)
559                 return sprintf(buf, "%u\n", osfs.os_bsize);
560
561         return rc;
562 }
563 LUSTRE_RO_ATTR(blocksize);
564
565 static ssize_t kbytestotal_show(struct kobject *kobj, struct attribute *attr,
566                                 char *buf)
567 {
568         struct obd_device *obd = container_of(kobj, struct obd_device,
569                                               obd_kobj);
570         struct obd_statfs  osfs;
571         int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
572                             cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
573                             OBD_STATFS_NODELAY);
574         if (!rc) {
575                 __u32 blk_size = osfs.os_bsize >> 10;
576                 __u64 result = osfs.os_blocks;
577
578                 while (blk_size >>= 1)
579                         result <<= 1;
580
581                 return sprintf(buf, "%llu\n", result);
582         }
583
584         return rc;
585 }
586 LUSTRE_RO_ATTR(kbytestotal);
587
588 static ssize_t kbytesfree_show(struct kobject *kobj, struct attribute *attr,
589                                char *buf)
590 {
591         struct obd_device *obd = container_of(kobj, struct obd_device,
592                                               obd_kobj);
593         struct obd_statfs  osfs;
594         int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
595                             cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
596                             OBD_STATFS_NODELAY);
597         if (!rc) {
598                 __u32 blk_size = osfs.os_bsize >> 10;
599                 __u64 result = osfs.os_bfree;
600
601                 while (blk_size >>= 1)
602                         result <<= 1;
603
604                 return sprintf(buf, "%llu\n", result);
605         }
606
607         return rc;
608 }
609 LUSTRE_RO_ATTR(kbytesfree);
610
611 static ssize_t kbytesavail_show(struct kobject *kobj, struct attribute *attr,
612                                 char *buf)
613 {
614         struct obd_device *obd = container_of(kobj, struct obd_device,
615                                               obd_kobj);
616         struct obd_statfs  osfs;
617         int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
618                             cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
619                             OBD_STATFS_NODELAY);
620         if (!rc) {
621                 __u32 blk_size = osfs.os_bsize >> 10;
622                 __u64 result = osfs.os_bavail;
623
624                 while (blk_size >>= 1)
625                         result <<= 1;
626
627                 return sprintf(buf, "%llu\n", result);
628         }
629
630         return rc;
631 }
632 LUSTRE_RO_ATTR(kbytesavail);
633
634 static ssize_t filestotal_show(struct kobject *kobj, struct attribute *attr,
635                                char *buf)
636 {
637         struct obd_device *obd = container_of(kobj, struct obd_device,
638                                               obd_kobj);
639         struct obd_statfs  osfs;
640         int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
641                             cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
642                             OBD_STATFS_NODELAY);
643         if (!rc)
644                 return sprintf(buf, "%llu\n", osfs.os_files);
645
646         return rc;
647 }
648 LUSTRE_RO_ATTR(filestotal);
649
650 static ssize_t filesfree_show(struct kobject *kobj, struct attribute *attr,
651                               char *buf)
652 {
653         struct obd_device *obd = container_of(kobj, struct obd_device,
654                                               obd_kobj);
655         struct obd_statfs  osfs;
656         int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
657                             cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
658                             OBD_STATFS_NODELAY);
659         if (!rc)
660                 return sprintf(buf, "%llu\n", osfs.os_ffree);
661
662         return rc;
663 }
664 LUSTRE_RO_ATTR(filesfree);
665
666 int lprocfs_rd_server_uuid(struct seq_file *m, void *data)
667 {
668         struct obd_device *obd = data;
669         struct obd_import *imp;
670         char *imp_state_name = NULL;
671
672         LASSERT(obd != NULL);
673         LPROCFS_CLIMP_CHECK(obd);
674         imp = obd->u.cli.cl_import;
675         imp_state_name = ptlrpc_import_state_name(imp->imp_state);
676         seq_printf(m, "%s\t%s%s\n",
677                    obd2cli_tgt(obd), imp_state_name,
678                    imp->imp_deactive ? "\tDEACTIVATED" : "");
679
680         LPROCFS_CLIMP_EXIT(obd);
681
682         return 0;
683 }
684 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
685
686 int lprocfs_rd_conn_uuid(struct seq_file *m, void *data)
687 {
688         struct obd_device *obd = data;
689         struct ptlrpc_connection *conn;
690
691         LASSERT(obd != NULL);
692
693         LPROCFS_CLIMP_CHECK(obd);
694         conn = obd->u.cli.cl_import->imp_connection;
695         if (conn && obd->u.cli.cl_import)
696                 seq_printf(m, "%s\n", conn->c_remote_uuid.uuid);
697         else
698                 seq_puts(m, "<none>\n");
699
700         LPROCFS_CLIMP_EXIT(obd);
701
702         return 0;
703 }
704 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
705
706 /** add up per-cpu counters */
707 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
708                            struct lprocfs_counter *cnt)
709 {
710         unsigned int                    num_entry;
711         struct lprocfs_counter          *percpu_cntr;
712         int                             i;
713         unsigned long                   flags = 0;
714
715         memset(cnt, 0, sizeof(*cnt));
716
717         if (stats == NULL) {
718                 /* set count to 1 to avoid divide-by-zero errs in callers */
719                 cnt->lc_count = 1;
720                 return;
721         }
722
723         cnt->lc_min = LC_MIN_INIT;
724
725         num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
726
727         for (i = 0; i < num_entry; i++) {
728                 if (stats->ls_percpu[i] == NULL)
729                         continue;
730                 percpu_cntr = lprocfs_stats_counter_get(stats, i, idx);
731
732                 cnt->lc_count += percpu_cntr->lc_count;
733                 cnt->lc_sum += percpu_cntr->lc_sum;
734                 if (percpu_cntr->lc_min < cnt->lc_min)
735                         cnt->lc_min = percpu_cntr->lc_min;
736                 if (percpu_cntr->lc_max > cnt->lc_max)
737                         cnt->lc_max = percpu_cntr->lc_max;
738                 cnt->lc_sumsquare += percpu_cntr->lc_sumsquare;
739         }
740
741         lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
742 }
743 EXPORT_SYMBOL(lprocfs_stats_collect);
744
745 /**
746  * Append a space separated list of current set flags to str.
747  */
748 #define flag2str(flag, first)                                           \
749         do {                                                            \
750                 if (imp->imp_##flag)                                    \
751                      seq_printf(m, "%s" #flag, first ? "" : ", ");      \
752         } while (0)
753 static int obd_import_flags2str(struct obd_import *imp, struct seq_file *m)
754 {
755         bool first = true;
756
757         if (imp->imp_obd->obd_no_recov) {
758                 seq_printf(m, "no_recov");
759                 first = false;
760         }
761
762         flag2str(invalid, first);
763         first = false;
764         flag2str(deactive, first);
765         flag2str(replayable, first);
766         flag2str(pingable, first);
767         return 0;
768 }
769 #undef flags2str
770
771 static void obd_connect_seq_flags2str(struct seq_file *m, __u64 flags, char *sep)
772 {
773         __u64 mask = 1;
774         int i;
775         bool first = true;
776
777         for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
778                 if (flags & mask) {
779                         seq_printf(m, "%s%s",
780                                         first ? sep : "", obd_connect_names[i]);
781                         first = false;
782                 }
783         }
784         if (flags & ~(mask - 1))
785                 seq_printf(m, "%sunknown flags %#llx",
786                                 first ? sep : "", flags & ~(mask - 1));
787 }
788
789 int lprocfs_rd_import(struct seq_file *m, void *data)
790 {
791         struct lprocfs_counter          ret;
792         struct lprocfs_counter_header   *header;
793         struct obd_device               *obd    = (struct obd_device *)data;
794         struct obd_import               *imp;
795         struct obd_import_conn          *conn;
796         int                             j;
797         int                             k;
798         int                             rw      = 0;
799
800         LASSERT(obd != NULL);
801         LPROCFS_CLIMP_CHECK(obd);
802         imp = obd->u.cli.cl_import;
803
804         seq_printf(m,
805                      "import:\n"
806                      "    name: %s\n"
807                      "    target: %s\n"
808                      "    state: %s\n"
809                      "    instance: %u\n"
810                      "    connect_flags: [",
811                      obd->obd_name,
812                      obd2cli_tgt(obd),
813                      ptlrpc_import_state_name(imp->imp_state),
814                      imp->imp_connect_data.ocd_instance);
815         obd_connect_seq_flags2str(m, imp->imp_connect_data.ocd_connect_flags, ", ");
816         seq_printf(m,
817                       "]\n"
818                       "    import_flags: [");
819         obd_import_flags2str(imp, m);
820
821         seq_printf(m,
822                       "]\n"
823                       "    connection:\n"
824                       "       failover_nids: [");
825         spin_lock(&imp->imp_lock);
826         j = 0;
827         list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
828                 seq_printf(m, "%s%s", j ? ", " : "",
829                            libcfs_nid2str(conn->oic_conn->c_peer.nid));
830                 j++;
831         }
832         seq_printf(m,
833                       "]\n"
834                       "       current_connection: %s\n"
835                       "       connection_attempts: %u\n"
836                       "       generation: %u\n"
837                       "       in-progress_invalidations: %u\n",
838                       imp->imp_connection == NULL ? "<none>" :
839                               libcfs_nid2str(imp->imp_connection->c_peer.nid),
840                       imp->imp_conn_cnt,
841                       imp->imp_generation,
842                       atomic_read(&imp->imp_inval_count));
843         spin_unlock(&imp->imp_lock);
844
845         if (obd->obd_svc_stats == NULL)
846                 goto out_climp;
847
848         header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
849         lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
850         if (ret.lc_count != 0) {
851                 /* first argument to do_div MUST be __u64 */
852                 __u64 sum = ret.lc_sum;
853                 do_div(sum, ret.lc_count);
854                 ret.lc_sum = sum;
855         } else
856                 ret.lc_sum = 0;
857         seq_printf(m,
858                       "    rpcs:\n"
859                       "       inflight: %u\n"
860                       "       unregistering: %u\n"
861                       "       timeouts: %u\n"
862                       "       avg_waittime: %llu %s\n",
863                       atomic_read(&imp->imp_inflight),
864                       atomic_read(&imp->imp_unregistering),
865                       atomic_read(&imp->imp_timeouts),
866                       ret.lc_sum, header->lc_units);
867
868         k = 0;
869         for (j = 0; j < IMP_AT_MAX_PORTALS; j++) {
870                 if (imp->imp_at.iat_portal[j] == 0)
871                         break;
872                 k = max_t(unsigned int, k,
873                           at_get(&imp->imp_at.iat_service_estimate[j]));
874         }
875         seq_printf(m,
876                       "    service_estimates:\n"
877                       "       services: %u sec\n"
878                       "       network: %u sec\n",
879                       k,
880                       at_get(&imp->imp_at.iat_net_latency));
881
882         seq_printf(m,
883                       "    transactions:\n"
884                       "       last_replay: %llu\n"
885                       "       peer_committed: %llu\n"
886                       "       last_checked: %llu\n",
887                       imp->imp_last_replay_transno,
888                       imp->imp_peer_committed_transno,
889                       imp->imp_last_transno_checked);
890
891         /* avg data rates */
892         for (rw = 0; rw <= 1; rw++) {
893                 lprocfs_stats_collect(obd->obd_svc_stats,
894                                       PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
895                                       &ret);
896                 if (ret.lc_sum > 0 && ret.lc_count > 0) {
897                         /* first argument to do_div MUST be __u64 */
898                         __u64 sum = ret.lc_sum;
899                         do_div(sum, ret.lc_count);
900                         ret.lc_sum = sum;
901                         seq_printf(m,
902                                       "    %s_data_averages:\n"
903                                       "       bytes_per_rpc: %llu\n",
904                                       rw ? "write" : "read",
905                                       ret.lc_sum);
906                 }
907                 k = (int)ret.lc_sum;
908                 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
909                 header = &obd->obd_svc_stats->ls_cnt_header[j];
910                 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
911                 if (ret.lc_sum > 0 && ret.lc_count != 0) {
912                         /* first argument to do_div MUST be __u64 */
913                         __u64 sum = ret.lc_sum;
914                         do_div(sum, ret.lc_count);
915                         ret.lc_sum = sum;
916                         seq_printf(m,
917                                       "       %s_per_rpc: %llu\n",
918                                       header->lc_units, ret.lc_sum);
919                         j = (int)ret.lc_sum;
920                         if (j > 0)
921                                 seq_printf(m,
922                                               "       MB_per_sec: %u.%.02u\n",
923                                               k / j, (100 * k / j) % 100);
924                 }
925         }
926
927 out_climp:
928         LPROCFS_CLIMP_EXIT(obd);
929         return 0;
930 }
931 EXPORT_SYMBOL(lprocfs_rd_import);
932
933 int lprocfs_rd_state(struct seq_file *m, void *data)
934 {
935         struct obd_device *obd = (struct obd_device *)data;
936         struct obd_import *imp;
937         int j, k;
938
939         LASSERT(obd != NULL);
940         LPROCFS_CLIMP_CHECK(obd);
941         imp = obd->u.cli.cl_import;
942
943         seq_printf(m, "current_state: %s\n",
944                      ptlrpc_import_state_name(imp->imp_state));
945         seq_printf(m, "state_history:\n");
946         k = imp->imp_state_hist_idx;
947         for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
948                 struct import_state_hist *ish =
949                         &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
950                 if (ish->ish_state == 0)
951                         continue;
952                 seq_printf(m, " - ["CFS_TIME_T", %s]\n",
953                               ish->ish_time,
954                               ptlrpc_import_state_name(ish->ish_state));
955         }
956
957         LPROCFS_CLIMP_EXIT(obd);
958         return 0;
959 }
960 EXPORT_SYMBOL(lprocfs_rd_state);
961
962 int lprocfs_at_hist_helper(struct seq_file *m, struct adaptive_timeout *at)
963 {
964         int i;
965         for (i = 0; i < AT_BINS; i++)
966                 seq_printf(m, "%3u ", at->at_hist[i]);
967         seq_printf(m, "\n");
968         return 0;
969 }
970 EXPORT_SYMBOL(lprocfs_at_hist_helper);
971
972 /* See also ptlrpc_lprocfs_rd_timeouts */
973 int lprocfs_rd_timeouts(struct seq_file *m, void *data)
974 {
975         struct obd_device *obd = (struct obd_device *)data;
976         struct obd_import *imp;
977         unsigned int cur, worst;
978         time_t now, worstt;
979         struct dhms ts;
980         int i;
981
982         LASSERT(obd != NULL);
983         LPROCFS_CLIMP_CHECK(obd);
984         imp = obd->u.cli.cl_import;
985
986         now = get_seconds();
987
988         /* Some network health info for kicks */
989         s2dhms(&ts, now - imp->imp_last_reply_time);
990         seq_printf(m, "%-10s : %ld, "DHMS_FMT" ago\n",
991                        "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
992
993         cur = at_get(&imp->imp_at.iat_net_latency);
994         worst = imp->imp_at.iat_net_latency.at_worst_ever;
995         worstt = imp->imp_at.iat_net_latency.at_worst_time;
996         s2dhms(&ts, now - worstt);
997         seq_printf(m, "%-10s : cur %3u  worst %3u (at %ld, "DHMS_FMT" ago) ",
998                        "network", cur, worst, worstt, DHMS_VARS(&ts));
999         lprocfs_at_hist_helper(m, &imp->imp_at.iat_net_latency);
1000
1001         for (i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1002                 if (imp->imp_at.iat_portal[i] == 0)
1003                         break;
1004                 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1005                 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1006                 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1007                 s2dhms(&ts, now - worstt);
1008                 seq_printf(m, "portal %-2d  : cur %3u  worst %3u (at %ld, "
1009                                DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1010                                cur, worst, worstt, DHMS_VARS(&ts));
1011                 lprocfs_at_hist_helper(m, &imp->imp_at.iat_service_estimate[i]);
1012         }
1013
1014         LPROCFS_CLIMP_EXIT(obd);
1015         return 0;
1016 }
1017 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1018
1019 int lprocfs_rd_connect_flags(struct seq_file *m, void *data)
1020 {
1021         struct obd_device *obd = data;
1022         __u64 flags;
1023
1024         LPROCFS_CLIMP_CHECK(obd);
1025         flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1026         seq_printf(m, "flags=%#llx\n", flags);
1027         obd_connect_seq_flags2str(m, flags, "\n");
1028         seq_printf(m, "\n");
1029         LPROCFS_CLIMP_EXIT(obd);
1030         return 0;
1031 }
1032 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1033
1034 static struct attribute *obd_def_attrs[] = {
1035         &lustre_attr_blocksize.attr,
1036         &lustre_attr_kbytestotal.attr,
1037         &lustre_attr_kbytesfree.attr,
1038         &lustre_attr_kbytesavail.attr,
1039         &lustre_attr_filestotal.attr,
1040         &lustre_attr_filesfree.attr,
1041         &lustre_attr_uuid.attr,
1042         NULL,
1043 };
1044
1045 static void obd_sysfs_release(struct kobject *kobj)
1046 {
1047         struct obd_device *obd = container_of(kobj, struct obd_device,
1048                                               obd_kobj);
1049
1050         complete(&obd->obd_kobj_unregister);
1051 }
1052
1053 static struct kobj_type obd_ktype = {
1054         .default_attrs  = obd_def_attrs,
1055         .sysfs_ops      = &lustre_sysfs_ops,
1056         .release        = obd_sysfs_release,
1057 };
1058
1059 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list,
1060                       struct attribute_group *attrs)
1061 {
1062         int rc = 0;
1063
1064         init_completion(&obd->obd_kobj_unregister);
1065         rc = kobject_init_and_add(&obd->obd_kobj, &obd_ktype,
1066                                   obd->obd_type->typ_kobj,
1067                                   "%s", obd->obd_name);
1068         if (rc)
1069                 return rc;
1070
1071         if (attrs) {
1072                 rc = sysfs_create_group(&obd->obd_kobj, attrs);
1073                 if (rc) {
1074                         kobject_put(&obd->obd_kobj);
1075                         return rc;
1076                 }
1077         }
1078
1079         obd->obd_debugfs_entry = ldebugfs_register(obd->obd_name,
1080                                                    obd->obd_type->typ_debugfs_entry,
1081                                                    list, obd);
1082         if (IS_ERR_OR_NULL(obd->obd_debugfs_entry)) {
1083                 rc = obd->obd_debugfs_entry ? PTR_ERR(obd->obd_debugfs_entry)
1084                                             : -ENOMEM;
1085                 CERROR("error %d setting up lprocfs for %s\n",
1086                        rc, obd->obd_name);
1087                 obd->obd_debugfs_entry = NULL;
1088         }
1089
1090         return rc;
1091 }
1092 EXPORT_SYMBOL(lprocfs_obd_setup);
1093
1094 int lprocfs_obd_cleanup(struct obd_device *obd)
1095 {
1096         if (!obd)
1097                 return -EINVAL;
1098
1099         if (!IS_ERR_OR_NULL(obd->obd_debugfs_entry))
1100                 ldebugfs_remove(&obd->obd_debugfs_entry);
1101
1102         kobject_put(&obd->obd_kobj);
1103         wait_for_completion(&obd->obd_kobj_unregister);
1104
1105         return 0;
1106 }
1107 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1108
1109 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1110 {
1111         CDEBUG(D_CONFIG, "stat %p - data %p/%p\n", client_stat,
1112                client_stat->nid_proc, client_stat->nid_stats);
1113
1114         LASSERTF(atomic_read(&client_stat->nid_exp_ref_count) == 0,
1115                  "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1116                  atomic_read(&client_stat->nid_exp_ref_count));
1117
1118         if (client_stat->nid_proc)
1119                 lprocfs_remove(&client_stat->nid_proc);
1120
1121         if (client_stat->nid_stats)
1122                 lprocfs_free_stats(&client_stat->nid_stats);
1123
1124         if (client_stat->nid_ldlm_stats)
1125                 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1126
1127         kfree(client_stat);
1128         return;
1129
1130 }
1131
1132 void lprocfs_free_per_client_stats(struct obd_device *obd)
1133 {
1134         struct cfs_hash *hash = obd->obd_nid_stats_hash;
1135         struct nid_stat *stat;
1136
1137         /* we need extra list - because hash_exit called to early */
1138         /* not need locking because all clients is died */
1139         while (!list_empty(&obd->obd_nid_stats)) {
1140                 stat = list_entry(obd->obd_nid_stats.next,
1141                                       struct nid_stat, nid_list);
1142                 list_del_init(&stat->nid_list);
1143                 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1144                 lprocfs_free_client_stats(stat);
1145         }
1146 }
1147 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1148
1149 int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid)
1150 {
1151         struct lprocfs_counter  *cntr;
1152         unsigned int            percpusize;
1153         int                     rc = -ENOMEM;
1154         unsigned long           flags = 0;
1155         int                     i;
1156
1157         LASSERT(stats->ls_percpu[cpuid] == NULL);
1158         LASSERT((stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) == 0);
1159
1160         percpusize = lprocfs_stats_counter_size(stats);
1161         LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[cpuid], percpusize);
1162         if (stats->ls_percpu[cpuid] != NULL) {
1163                 rc = 0;
1164                 if (unlikely(stats->ls_biggest_alloc_num <= cpuid)) {
1165                         if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1166                                 spin_lock_irqsave(&stats->ls_lock, flags);
1167                         else
1168                                 spin_lock(&stats->ls_lock);
1169                         if (stats->ls_biggest_alloc_num <= cpuid)
1170                                 stats->ls_biggest_alloc_num = cpuid + 1;
1171                         if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1172                                 spin_unlock_irqrestore(&stats->ls_lock, flags);
1173                         else
1174                                 spin_unlock(&stats->ls_lock);
1175                 }
1176                 /* initialize the ls_percpu[cpuid] non-zero counter */
1177                 for (i = 0; i < stats->ls_num; ++i) {
1178                         cntr = lprocfs_stats_counter_get(stats, cpuid, i);
1179                         cntr->lc_min = LC_MIN_INIT;
1180                 }
1181         }
1182         return rc;
1183 }
1184 EXPORT_SYMBOL(lprocfs_stats_alloc_one);
1185
1186 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1187                                           enum lprocfs_stats_flags flags)
1188 {
1189         struct lprocfs_stats    *stats;
1190         unsigned int            num_entry;
1191         unsigned int            percpusize = 0;
1192         int                     i;
1193
1194         if (num == 0)
1195                 return NULL;
1196
1197         if (lprocfs_no_percpu_stats != 0)
1198                 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1199
1200         if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1201                 num_entry = 1;
1202         else
1203                 num_entry = num_possible_cpus();
1204
1205         /* alloc percpu pointers for all possible cpu slots */
1206         LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1207         if (stats == NULL)
1208                 return NULL;
1209
1210         stats->ls_num = num;
1211         stats->ls_flags = flags;
1212         spin_lock_init(&stats->ls_lock);
1213
1214         /* alloc num of counter headers */
1215         LIBCFS_ALLOC(stats->ls_cnt_header,
1216                      stats->ls_num * sizeof(struct lprocfs_counter_header));
1217         if (stats->ls_cnt_header == NULL)
1218                 goto fail;
1219
1220         if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
1221                 /* contains only one set counters */
1222                 percpusize = lprocfs_stats_counter_size(stats);
1223                 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
1224                 if (stats->ls_percpu[0] == NULL)
1225                         goto fail;
1226                 stats->ls_biggest_alloc_num = 1;
1227         } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
1228                 /* alloc all percpu data, currently only obd_memory use this */
1229                 for (i = 0; i < num_entry; ++i)
1230                         if (lprocfs_stats_alloc_one(stats, i) < 0)
1231                                 goto fail;
1232         }
1233
1234         return stats;
1235
1236 fail:
1237         lprocfs_free_stats(&stats);
1238         return NULL;
1239 }
1240 EXPORT_SYMBOL(lprocfs_alloc_stats);
1241
1242 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1243 {
1244         struct lprocfs_stats *stats = *statsh;
1245         unsigned int num_entry;
1246         unsigned int percpusize;
1247         unsigned int i;
1248
1249         if (stats == NULL || stats->ls_num == 0)
1250                 return;
1251         *statsh = NULL;
1252
1253         if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1254                 num_entry = 1;
1255         else
1256                 num_entry = num_possible_cpus();
1257
1258         percpusize = lprocfs_stats_counter_size(stats);
1259         for (i = 0; i < num_entry; i++)
1260                 if (stats->ls_percpu[i] != NULL)
1261                         LIBCFS_FREE(stats->ls_percpu[i], percpusize);
1262         if (stats->ls_cnt_header != NULL)
1263                 LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
1264                                         sizeof(struct lprocfs_counter_header));
1265         LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1266 }
1267 EXPORT_SYMBOL(lprocfs_free_stats);
1268
1269 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1270 {
1271         struct lprocfs_counter          *percpu_cntr;
1272         int                             i;
1273         int                             j;
1274         unsigned int                    num_entry;
1275         unsigned long                   flags = 0;
1276
1277         num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1278
1279         for (i = 0; i < num_entry; i++) {
1280                 if (stats->ls_percpu[i] == NULL)
1281                         continue;
1282                 for (j = 0; j < stats->ls_num; j++) {
1283                         percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
1284                         percpu_cntr->lc_count           = 0;
1285                         percpu_cntr->lc_min             = LC_MIN_INIT;
1286                         percpu_cntr->lc_max             = 0;
1287                         percpu_cntr->lc_sumsquare       = 0;
1288                         percpu_cntr->lc_sum             = 0;
1289                         if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1290                                 percpu_cntr->lc_sum_irq = 0;
1291                 }
1292         }
1293
1294         lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1295 }
1296 EXPORT_SYMBOL(lprocfs_clear_stats);
1297
1298 static ssize_t lprocfs_stats_seq_write(struct file *file,
1299                                        const char __user *buf,
1300                                        size_t len, loff_t *off)
1301 {
1302         struct seq_file *seq = file->private_data;
1303         struct lprocfs_stats *stats = seq->private;
1304
1305         lprocfs_clear_stats(stats);
1306
1307         return len;
1308 }
1309
1310 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1311 {
1312         struct lprocfs_stats *stats = p->private;
1313
1314         return (*pos < stats->ls_num) ? pos : NULL;
1315 }
1316
1317 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1318 {
1319 }
1320
1321 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1322 {
1323         (*pos)++;
1324         return lprocfs_stats_seq_start(p, pos);
1325 }
1326
1327 /* seq file export of one lprocfs counter */
1328 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1329 {
1330         struct lprocfs_stats            *stats  = p->private;
1331         struct lprocfs_counter_header   *hdr;
1332         struct lprocfs_counter           ctr;
1333         int                              idx    = *(loff_t *)v;
1334
1335         if (idx == 0) {
1336                 struct timeval now;
1337                 do_gettimeofday(&now);
1338                 seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1339                            "snapshot_time",
1340                            now.tv_sec, (unsigned long)now.tv_usec);
1341         }
1342
1343         hdr = &stats->ls_cnt_header[idx];
1344         lprocfs_stats_collect(stats, idx, &ctr);
1345
1346         if (ctr.lc_count != 0) {
1347                 seq_printf(p, "%-25s %lld samples [%s]",
1348                            hdr->lc_name, ctr.lc_count, hdr->lc_units);
1349
1350                 if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) &&
1351                     (ctr.lc_count > 0)) {
1352                         seq_printf(p, " %lld %lld %lld",
1353                                    ctr.lc_min, ctr.lc_max, ctr.lc_sum);
1354                         if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
1355                                 seq_printf(p, " %lld", ctr.lc_sumsquare);
1356                 }
1357                 seq_putc(p, '\n');
1358         }
1359
1360         return 0;
1361 }
1362
1363 static const struct seq_operations lprocfs_stats_seq_sops = {
1364         .start  = lprocfs_stats_seq_start,
1365         .stop   = lprocfs_stats_seq_stop,
1366         .next   = lprocfs_stats_seq_next,
1367         .show   = lprocfs_stats_seq_show,
1368 };
1369
1370 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1371 {
1372         struct seq_file *seq;
1373         int rc;
1374
1375         rc = seq_open(file, &lprocfs_stats_seq_sops);
1376         if (rc)
1377                 return rc;
1378
1379         seq = file->private_data;
1380         seq->private = inode->i_private ?: PDE_DATA(inode);
1381
1382         return 0;
1383 }
1384
1385 struct file_operations lprocfs_stats_seq_fops = {
1386         .owner   = THIS_MODULE,
1387         .open    = lprocfs_stats_seq_open,
1388         .read    = seq_read,
1389         .write   = lprocfs_stats_seq_write,
1390         .llseek  = seq_lseek,
1391         .release = lprocfs_seq_release,
1392 };
1393
1394 int ldebugfs_register_stats(struct dentry *parent, const char *name,
1395                            struct lprocfs_stats *stats)
1396 {
1397         struct dentry *entry;
1398
1399         LASSERT(!IS_ERR_OR_NULL(parent));
1400
1401         entry = debugfs_create_file(name, 0644, parent, stats,
1402                                     &lprocfs_stats_seq_fops);
1403         if (IS_ERR_OR_NULL(entry))
1404                 return entry ? PTR_ERR(entry) : -ENOMEM;
1405
1406         return 0;
1407 }
1408 EXPORT_SYMBOL(ldebugfs_register_stats);
1409
1410 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1411                            struct lprocfs_stats *stats)
1412 {
1413         struct proc_dir_entry *entry;
1414         LASSERT(root != NULL);
1415
1416         entry = proc_create_data(name, 0644, root,
1417                                  &lprocfs_stats_seq_fops, stats);
1418         if (entry == NULL)
1419                 return -ENOMEM;
1420
1421         return 0;
1422 }
1423 EXPORT_SYMBOL(lprocfs_register_stats);
1424
1425 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1426                           unsigned conf, const char *name, const char *units)
1427 {
1428         struct lprocfs_counter_header   *header;
1429         struct lprocfs_counter          *percpu_cntr;
1430         unsigned long                   flags = 0;
1431         unsigned int                    i;
1432         unsigned int                    num_cpu;
1433
1434         LASSERT(stats != NULL);
1435
1436         header = &stats->ls_cnt_header[index];
1437         LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
1438                  index, name, units);
1439
1440         header->lc_config = conf;
1441         header->lc_name   = name;
1442         header->lc_units  = units;
1443
1444         num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1445         for (i = 0; i < num_cpu; ++i) {
1446                 if (stats->ls_percpu[i] == NULL)
1447                         continue;
1448                 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
1449                 percpu_cntr->lc_count           = 0;
1450                 percpu_cntr->lc_min             = LC_MIN_INIT;
1451                 percpu_cntr->lc_max             = 0;
1452                 percpu_cntr->lc_sumsquare       = 0;
1453                 percpu_cntr->lc_sum             = 0;
1454                 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
1455                         percpu_cntr->lc_sum_irq = 0;
1456         }
1457         lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1458 }
1459 EXPORT_SYMBOL(lprocfs_counter_init);
1460
1461 #define LPROCFS_OBD_OP_INIT(base, stats, op)                           \
1462 do {                                                                   \
1463         unsigned int coffset = base + OBD_COUNTER_OFFSET(op);         \
1464         LASSERT(coffset < stats->ls_num);                                 \
1465         lprocfs_counter_init(stats, coffset, 0, #op, "reqs");         \
1466 } while (0)
1467
1468 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1469 {
1470         LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1471         LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1472         LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1473         LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1474         LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1475         LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1476         LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1477         LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1478         LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1479         LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1480         LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1481         LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1482         LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1483         LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1484         LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1485         LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1486         LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1487         LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1488         LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1489         LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1490         LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1491         LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1492         LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1493         LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1494         LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1495         LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1496         LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1497         LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1498         LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1499         LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1500         LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1501         LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1502         LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1503         LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1504         LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1505         LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1506         LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1507         LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1508         LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1509         LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1510         LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1511         LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1512         LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1513         LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1514         LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1515         LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1516         LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1517 }
1518 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1519
1520 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1521 {
1522         struct lprocfs_stats *stats;
1523         unsigned int num_stats;
1524         int rc, i;
1525
1526         LASSERT(obd->obd_stats == NULL);
1527         LASSERT(obd->obd_debugfs_entry != NULL);
1528         LASSERT(obd->obd_cntr_base == 0);
1529
1530         num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1531                 num_private_stats - 1 /* o_owner */;
1532         stats = lprocfs_alloc_stats(num_stats, 0);
1533         if (stats == NULL)
1534                 return -ENOMEM;
1535
1536         lprocfs_init_ops_stats(num_private_stats, stats);
1537
1538         for (i = num_private_stats; i < num_stats; i++) {
1539                 /* If this LBUGs, it is likely that an obd
1540                  * operation was added to struct obd_ops in
1541                  * <obd.h>, and that the corresponding line item
1542                  * LPROCFS_OBD_OP_INIT(.., .., opname)
1543                  * is missing from the list above. */
1544                 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
1545                          "Missing obd_stat initializer obd_op operation at offset %d.\n",
1546                          i - num_private_stats);
1547         }
1548         rc = ldebugfs_register_stats(obd->obd_debugfs_entry, "stats", stats);
1549         if (rc < 0) {
1550                 lprocfs_free_stats(&stats);
1551         } else {
1552                 obd->obd_stats  = stats;
1553                 obd->obd_cntr_base = num_private_stats;
1554         }
1555         return rc;
1556 }
1557 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1558
1559 void lprocfs_free_obd_stats(struct obd_device *obd)
1560 {
1561         if (obd->obd_stats)
1562                 lprocfs_free_stats(&obd->obd_stats);
1563 }
1564 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1565
1566 #define LPROCFS_MD_OP_INIT(base, stats, op)                          \
1567 do {                                                                \
1568         unsigned int coffset = base + MD_COUNTER_OFFSET(op);        \
1569         LASSERT(coffset < stats->ls_num);                              \
1570         lprocfs_counter_init(stats, coffset, 0, #op, "reqs");      \
1571 } while (0)
1572
1573 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1574 {
1575         LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1576         LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
1577         LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1578         LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1579         LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1580         LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1581         LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1582         LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1583         LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1584         LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1585         LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1586         LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1587         LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1588         LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1589         LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1590         LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1591         LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1592         LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1593         LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1594         LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1595         LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1596         LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1597         LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1598         LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1599         LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1600         LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1601         LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1602         LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1603         LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1604         LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1605         LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1606         LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1607 }
1608 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1609
1610 int lprocfs_alloc_md_stats(struct obd_device *obd,
1611                            unsigned num_private_stats)
1612 {
1613         struct lprocfs_stats *stats;
1614         unsigned int num_stats;
1615         int rc, i;
1616
1617         LASSERT(obd->md_stats == NULL);
1618         LASSERT(obd->obd_debugfs_entry != NULL);
1619         LASSERT(obd->md_cntr_base == 0);
1620
1621         num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1622                     num_private_stats;
1623         stats = lprocfs_alloc_stats(num_stats, 0);
1624         if (stats == NULL)
1625                 return -ENOMEM;
1626
1627         lprocfs_init_mps_stats(num_private_stats, stats);
1628
1629         for (i = num_private_stats; i < num_stats; i++) {
1630                 if (stats->ls_cnt_header[i].lc_name == NULL) {
1631                         CERROR("Missing md_stat initializer md_op operation at offset %d. Aborting.\n",
1632                                i - num_private_stats);
1633                         LBUG();
1634                 }
1635         }
1636         rc = ldebugfs_register_stats(obd->obd_debugfs_entry, "md_stats", stats);
1637         if (rc < 0) {
1638                 lprocfs_free_stats(&stats);
1639         } else {
1640                 obd->md_stats  = stats;
1641                 obd->md_cntr_base = num_private_stats;
1642         }
1643         return rc;
1644 }
1645 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1646
1647 void lprocfs_free_md_stats(struct obd_device *obd)
1648 {
1649         struct lprocfs_stats *stats = obd->md_stats;
1650
1651         if (stats != NULL) {
1652                 obd->md_stats = NULL;
1653                 obd->md_cntr_base = 0;
1654                 lprocfs_free_stats(&stats);
1655         }
1656 }
1657 EXPORT_SYMBOL(lprocfs_free_md_stats);
1658
1659 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1660 {
1661         lprocfs_counter_init(ldlm_stats,
1662                              LDLM_ENQUEUE - LDLM_FIRST_OPC,
1663                              0, "ldlm_enqueue", "reqs");
1664         lprocfs_counter_init(ldlm_stats,
1665                              LDLM_CONVERT - LDLM_FIRST_OPC,
1666                              0, "ldlm_convert", "reqs");
1667         lprocfs_counter_init(ldlm_stats,
1668                              LDLM_CANCEL - LDLM_FIRST_OPC,
1669                              0, "ldlm_cancel", "reqs");
1670         lprocfs_counter_init(ldlm_stats,
1671                              LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1672                              0, "ldlm_bl_callback", "reqs");
1673         lprocfs_counter_init(ldlm_stats,
1674                              LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1675                              0, "ldlm_cp_callback", "reqs");
1676         lprocfs_counter_init(ldlm_stats,
1677                              LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1678                              0, "ldlm_gl_callback", "reqs");
1679 }
1680 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1681
1682 int lprocfs_nid_stats_clear_read(struct seq_file *m, void *data)
1683 {
1684         seq_printf(m, "%s\n",
1685                    "Write into this file to clear all nid stats and stale nid entries");
1686         return 0;
1687 }
1688 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1689
1690 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1691 {
1692         struct nid_stat *stat = obj;
1693
1694         CDEBUG(D_INFO, "refcnt %d\n", atomic_read(&stat->nid_exp_ref_count));
1695         if (atomic_read(&stat->nid_exp_ref_count) == 1) {
1696                 /* object has only hash references. */
1697                 spin_lock(&stat->nid_obd->obd_nid_lock);
1698                 list_move(&stat->nid_list, data);
1699                 spin_unlock(&stat->nid_obd->obd_nid_lock);
1700                 return 1;
1701         }
1702         /* we has reference to object - only clear data*/
1703         if (stat->nid_stats)
1704                 lprocfs_clear_stats(stat->nid_stats);
1705
1706         return 0;
1707 }
1708
1709 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1710                                   unsigned long count, void *data)
1711 {
1712         struct obd_device *obd = (struct obd_device *)data;
1713         struct nid_stat *client_stat;
1714         LIST_HEAD(free_list);
1715
1716         cfs_hash_cond_del(obd->obd_nid_stats_hash,
1717                           lprocfs_nid_stats_clear_write_cb, &free_list);
1718
1719         while (!list_empty(&free_list)) {
1720                 client_stat = list_entry(free_list.next, struct nid_stat,
1721                                              nid_list);
1722                 list_del_init(&client_stat->nid_list);
1723                 lprocfs_free_client_stats(client_stat);
1724         }
1725
1726         return count;
1727 }
1728 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1729
1730 int lprocfs_exp_cleanup(struct obd_export *exp)
1731 {
1732         struct nid_stat *stat = exp->exp_nid_stats;
1733
1734         if (!stat || !exp->exp_obd)
1735                 return 0;
1736
1737         nidstat_putref(exp->exp_nid_stats);
1738         exp->exp_nid_stats = NULL;
1739
1740         return 0;
1741 }
1742 EXPORT_SYMBOL(lprocfs_exp_cleanup);
1743
1744 __s64 lprocfs_read_helper(struct lprocfs_counter *lc,
1745                           struct lprocfs_counter_header *header,
1746                           enum lprocfs_stats_flags flags,
1747                           enum lprocfs_fields_flags field)
1748 {
1749         __s64 ret = 0;
1750
1751         if (lc == NULL || header == NULL)
1752                 return 0;
1753
1754         switch (field) {
1755         case LPROCFS_FIELDS_FLAGS_CONFIG:
1756                 ret = header->lc_config;
1757                 break;
1758         case LPROCFS_FIELDS_FLAGS_SUM:
1759                 ret = lc->lc_sum;
1760                 if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
1761                         ret += lc->lc_sum_irq;
1762                 break;
1763         case LPROCFS_FIELDS_FLAGS_MIN:
1764                 ret = lc->lc_min;
1765                 break;
1766         case LPROCFS_FIELDS_FLAGS_MAX:
1767                 ret = lc->lc_max;
1768                 break;
1769         case LPROCFS_FIELDS_FLAGS_AVG:
1770                 ret = (lc->lc_max - lc->lc_min) / 2;
1771                 break;
1772         case LPROCFS_FIELDS_FLAGS_SUMSQUARE:
1773                 ret = lc->lc_sumsquare;
1774                 break;
1775         case LPROCFS_FIELDS_FLAGS_COUNT:
1776                 ret = lc->lc_count;
1777                 break;
1778         default:
1779                 break;
1780         }
1781
1782         return 0;
1783 }
1784 EXPORT_SYMBOL(lprocfs_read_helper);
1785
1786 int lprocfs_write_helper(const char __user *buffer, unsigned long count,
1787                          int *val)
1788 {
1789         return lprocfs_write_frac_helper(buffer, count, val, 1);
1790 }
1791 EXPORT_SYMBOL(lprocfs_write_helper);
1792
1793 int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult)
1794 {
1795         long decimal_val, frac_val;
1796
1797         decimal_val = val / mult;
1798         seq_printf(m, "%ld", decimal_val);
1799         frac_val = val % mult;
1800
1801         if (frac_val > 0) {
1802                 frac_val *= 100;
1803                 frac_val /= mult;
1804         }
1805         if (frac_val > 0) {
1806                 /* Three cases: x0, xx, 0x */
1807                 if ((frac_val % 10) != 0)
1808                         seq_printf(m, ".%ld", frac_val);
1809                 else
1810                         seq_printf(m, ".%ld", frac_val / 10);
1811         }
1812
1813         seq_printf(m, "\n");
1814         return 0;
1815 }
1816 EXPORT_SYMBOL(lprocfs_seq_read_frac_helper);
1817
1818 int lprocfs_write_u64_helper(const char __user *buffer, unsigned long count,
1819                              __u64 *val)
1820 {
1821         return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1822 }
1823 EXPORT_SYMBOL(lprocfs_write_u64_helper);
1824
1825 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1826                               __u64 *val, int mult)
1827 {
1828         char kernbuf[22], *end, *pbuf;
1829         __u64 whole, frac = 0, units;
1830         unsigned frac_d = 1;
1831         int sign = 1;
1832
1833         if (count > (sizeof(kernbuf) - 1))
1834                 return -EINVAL;
1835
1836         if (copy_from_user(kernbuf, buffer, count))
1837                 return -EFAULT;
1838
1839         kernbuf[count] = '\0';
1840         pbuf = kernbuf;
1841         if (*pbuf == '-') {
1842                 sign = -1;
1843                 pbuf++;
1844         }
1845
1846         whole = simple_strtoull(pbuf, &end, 10);
1847         if (pbuf == end)
1848                 return -EINVAL;
1849
1850         if (*end == '.') {
1851                 int i;
1852                 pbuf = end + 1;
1853
1854                 /* need to limit frac_d to a __u32 */
1855                 if (strlen(pbuf) > 10)
1856                         pbuf[10] = '\0';
1857
1858                 frac = simple_strtoull(pbuf, &end, 10);
1859                 /* count decimal places */
1860                 for (i = 0; i < (end - pbuf); i++)
1861                         frac_d *= 10;
1862         }
1863
1864         units = 1;
1865         switch (tolower(*end)) {
1866         case 'p':
1867                 units <<= 10;
1868         case 't':
1869                 units <<= 10;
1870         case 'g':
1871                 units <<= 10;
1872         case 'm':
1873                 units <<= 10;
1874         case 'k':
1875                 units <<= 10;
1876         }
1877         /* Specified units override the multiplier */
1878         if (units > 1)
1879                 mult = units;
1880
1881         frac *= mult;
1882         do_div(frac, frac_d);
1883         *val = sign * (whole * mult + frac);
1884         return 0;
1885 }
1886 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
1887
1888 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
1889 {
1890         size_t l2;
1891
1892         l2 = strlen(s2);
1893         if (!l2)
1894                 return (char *)s1;
1895         while (len >= l2) {
1896                 len--;
1897                 if (!memcmp(s1, s2, l2))
1898                         return (char *)s1;
1899                 s1++;
1900         }
1901         return NULL;
1902 }
1903
1904 /**
1905  * Find the string \a name in the input \a buffer, and return a pointer to the
1906  * value immediately following \a name, reducing \a count appropriately.
1907  * If \a name is not found the original \a buffer is returned.
1908  */
1909 char *lprocfs_find_named_value(const char *buffer, const char *name,
1910                                size_t *count)
1911 {
1912         char *val;
1913         size_t buflen = *count;
1914
1915         /* there is no strnstr() in rhel5 and ubuntu kernels */
1916         val = lprocfs_strnstr(buffer, name, buflen);
1917         if (val == NULL)
1918                 return (char *)buffer;
1919
1920         val += strlen(name);                         /* skip prefix */
1921         while (val < buffer + buflen && isspace(*val)) /* skip separator */
1922                 val++;
1923
1924         *count = 0;
1925         while (val < buffer + buflen && isalnum(*val)) {
1926                 ++*count;
1927                 ++val;
1928         }
1929
1930         return val - *count;
1931 }
1932 EXPORT_SYMBOL(lprocfs_find_named_value);
1933
1934 int ldebugfs_seq_create(struct dentry *parent,
1935                        const char *name,
1936                        umode_t mode,
1937                        const struct file_operations *seq_fops,
1938                        void *data)
1939 {
1940         struct dentry *entry;
1941
1942         /* Disallow secretly (un)writable entries. */
1943         LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
1944
1945         entry = debugfs_create_file(name, mode, parent, data, seq_fops);
1946         if (IS_ERR_OR_NULL(entry))
1947                 return entry ? PTR_ERR(entry) : -ENOMEM;
1948
1949         return 0;
1950 }
1951 EXPORT_SYMBOL(ldebugfs_seq_create);
1952
1953 int lprocfs_seq_create(struct proc_dir_entry *parent,
1954                        const char *name,
1955                        umode_t mode,
1956                        const struct file_operations *seq_fops,
1957                        void *data)
1958 {
1959         struct proc_dir_entry *entry;
1960
1961         /* Disallow secretly (un)writable entries. */
1962         LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
1963         entry = proc_create_data(name, mode, parent, seq_fops, data);
1964
1965         if (entry == NULL)
1966                 return -ENOMEM;
1967
1968         return 0;
1969 }
1970 EXPORT_SYMBOL(lprocfs_seq_create);
1971
1972 int lprocfs_obd_seq_create(struct obd_device *dev,
1973                            const char *name,
1974                            umode_t mode,
1975                            const struct file_operations *seq_fops,
1976                            void *data)
1977 {
1978         return ldebugfs_seq_create(dev->obd_debugfs_entry, name,
1979                                    mode, seq_fops, data);
1980 }
1981 EXPORT_SYMBOL(lprocfs_obd_seq_create);
1982
1983 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
1984 {
1985         if (value >= OBD_HIST_MAX)
1986                 value = OBD_HIST_MAX - 1;
1987
1988         spin_lock(&oh->oh_lock);
1989         oh->oh_buckets[value]++;
1990         spin_unlock(&oh->oh_lock);
1991 }
1992 EXPORT_SYMBOL(lprocfs_oh_tally);
1993
1994 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
1995 {
1996         unsigned int val;
1997
1998         for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
1999                 ;
2000
2001         lprocfs_oh_tally(oh, val);
2002 }
2003 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2004
2005 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2006 {
2007         unsigned long ret = 0;
2008         int i;
2009
2010         for (i = 0; i < OBD_HIST_MAX; i++)
2011                 ret +=  oh->oh_buckets[i];
2012         return ret;
2013 }
2014 EXPORT_SYMBOL(lprocfs_oh_sum);
2015
2016 void lprocfs_oh_clear(struct obd_histogram *oh)
2017 {
2018         spin_lock(&oh->oh_lock);
2019         memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2020         spin_unlock(&oh->oh_lock);
2021 }
2022 EXPORT_SYMBOL(lprocfs_oh_clear);
2023
2024 int lprocfs_obd_rd_max_pages_per_rpc(struct seq_file *m, void *data)
2025 {
2026         struct obd_device *dev = data;
2027         struct client_obd *cli = &dev->u.cli;
2028
2029         client_obd_list_lock(&cli->cl_loi_list_lock);
2030         seq_printf(m, "%d\n", cli->cl_max_pages_per_rpc);
2031         client_obd_list_unlock(&cli->cl_loi_list_lock);
2032
2033         return 0;
2034 }
2035 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2036
2037 #endif
2038
2039 ssize_t lustre_attr_show(struct kobject *kobj,
2040                          struct attribute *attr, char *buf)
2041 {
2042         struct lustre_attr *a = container_of(attr, struct lustre_attr, attr);
2043
2044         return a->show ? a->show(kobj, attr, buf) : 0;
2045 }
2046 EXPORT_SYMBOL_GPL(lustre_attr_show);
2047
2048 ssize_t lustre_attr_store(struct kobject *kobj, struct attribute *attr,
2049                           const char *buf, size_t len)
2050 {
2051         struct lustre_attr *a = container_of(attr, struct lustre_attr, attr);
2052
2053         return a->store ? a->store(kobj, attr, buf, len) : len;
2054 }
2055 EXPORT_SYMBOL_GPL(lustre_attr_store);
2056
2057 const struct sysfs_ops lustre_sysfs_ops = {
2058         .show  = lustre_attr_show,
2059         .store = lustre_attr_store,
2060 };
2061 EXPORT_SYMBOL_GPL(lustre_sysfs_ops);