Whamcloud - gitweb
LU-17662 osd-zfs: Support for ZFS 2.2.3
[fs/lustre-release.git] / lustre / obdclass / lprocfs_status_server.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.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2014, 2017, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  *
31  * lustre/obdclass/lprocfs_status_server.c
32  */
33
34 #define DEBUG_SUBSYSTEM S_CLASS
35
36 #include <linux/kobject.h>
37 #include <linux/sysfs.h>
38
39 #include <obd_class.h>
40 #include <lprocfs_status.h>
41 #include <lustre_nodemap.h>
42
43 #define MAX_STRING_SIZE 128
44
45 struct dentry *ldebugfs_add_symlink(const char *name, const char *target,
46                                     const char *format, ...)
47 {
48         struct dentry *entry = NULL;
49         struct dentry *parent;
50         struct qstr dname;
51         va_list ap;
52         char *dest;
53
54         if (!target || !format)
55                 return NULL;
56
57         dname.name = target;
58         dname.len = strlen(dname.name);
59         dname.hash = ll_full_name_hash(debugfs_lustre_root,
60                                        dname.name, dname.len);
61         parent = d_lookup(debugfs_lustre_root, &dname);
62         if (!parent)
63                 return NULL;
64
65         OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
66         if (!dest)
67                 goto no_entry;
68
69         va_start(ap, format);
70         vsnprintf(dest, MAX_STRING_SIZE, format, ap);
71         va_end(ap);
72
73         entry = debugfs_create_symlink(name, parent, dest);
74
75         OBD_FREE(dest, MAX_STRING_SIZE + 1);
76 no_entry:
77         dput(parent);
78         return entry;
79 }
80 EXPORT_SYMBOL(ldebugfs_add_symlink);
81
82 int lprocfs_recovery_stale_clients_seq_show(struct seq_file *m, void *data)
83 {
84         struct obd_device *obd = m->private;
85         struct obd_export *exp, *n;
86         int connected;
87
88         if (!obd->obd_recovering ||
89             atomic_read(&obd->obd_connected_clients) >=
90             atomic_read(&obd->obd_max_recoverable_clients))
91                 /* not in recovery */
92                 return 0;
93
94         spin_lock(&obd->obd_dev_lock);
95         list_for_each_entry_safe(exp, n, &obd->obd_exports, exp_obd_chain) {
96                 /* don't count self-export as client */
97                 if (obd_uuid_equals(&exp->exp_client_uuid,
98                                     &exp->exp_obd->obd_uuid))
99                         continue;
100
101                 /* don't count clients which have no slot in last_rcvd
102                  * (e.g. lightweight connection)
103                  */
104                 if (exp->exp_target_data.ted_lr_idx == -1)
105                         continue;
106
107                 connected = !exp->exp_failed && (exp->exp_conn_cnt > 0);
108
109                 if (!connected)
110                         seq_printf(m, "%s\n", exp->exp_client_uuid.uuid);
111         }
112         spin_unlock(&obd->obd_dev_lock);
113
114         return 0;
115 }
116 EXPORT_SYMBOL(lprocfs_recovery_stale_clients_seq_show);
117
118 #ifdef CONFIG_PROC_FS
119 #define BUFLEN (UUID_MAX + 5)
120
121 ssize_t
122 lprocfs_evict_client_seq_write(struct file *file, const char __user *buffer,
123                                size_t count, loff_t *off)
124 {
125         struct seq_file *m = file->private_data;
126         struct obd_device *obd = m->private;
127         char *tmpbuf, *kbuf;
128
129         OBD_ALLOC(kbuf, BUFLEN);
130         if (kbuf == NULL)
131                 return -ENOMEM;
132
133         /*
134          * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1
135          * bytes into kbuf, to ensure that the string is NUL-terminated.
136          * UUID_MAX should include a trailing NUL already.
137          */
138         if (copy_from_user(kbuf, buffer,
139                            min_t(unsigned long, BUFLEN - 1, count))) {
140                 count = -EFAULT;
141                 goto out;
142         }
143         tmpbuf = skip_spaces(kbuf);
144         tmpbuf = strsep(&tmpbuf, " \t\n\f\v\r");
145         class_incref(obd, __func__, current);
146
147         if (strncmp(tmpbuf, "nid:", 4) == 0)
148                 obd_export_evict_by_nid(obd, tmpbuf + 4);
149         else if (strncmp(tmpbuf, "uuid:", 5) == 0)
150                 obd_export_evict_by_uuid(obd, tmpbuf + 5);
151         else
152                 obd_export_evict_by_uuid(obd, tmpbuf);
153
154         class_decref(obd, __func__, current);
155
156 out:
157         OBD_FREE(kbuf, BUFLEN);
158         return count;
159 }
160 EXPORT_SYMBOL(lprocfs_evict_client_seq_write);
161
162 #undef BUFLEN
163
164 ssize_t eviction_count_show(struct kobject *kobj, struct attribute *attr,
165                          char *buf)
166 {
167         struct obd_device *obd = container_of(kobj, struct obd_device,
168                                               obd_kset.kobj);
169
170         return scnprintf(buf, PAGE_SIZE, "%u\n",
171                          atomic_read(&obd->obd_eviction_count));
172 }
173 EXPORT_SYMBOL(eviction_count_show);
174
175 ssize_t num_exports_show(struct kobject *kobj, struct attribute *attr,
176                          char *buf)
177 {
178         struct obd_device *obd = container_of(kobj, struct obd_device,
179                                               obd_kset.kobj);
180
181         return scnprintf(buf, PAGE_SIZE, "%u\n", obd->obd_num_exports);
182 }
183 EXPORT_SYMBOL(num_exports_show);
184
185 ssize_t grant_check_threshold_show(struct kobject *kobj, struct attribute *attr,
186                                    char *buf)
187 {
188         struct obd_device *obd = container_of(kobj, struct obd_device,
189                                               obd_kset.kobj);
190
191         return scnprintf(buf, PAGE_SIZE, "%d\n",
192                          obd->obd_grant_check_threshold);
193 }
194 EXPORT_SYMBOL(grant_check_threshold_show);
195
196 ssize_t grant_check_threshold_store(struct kobject *kobj,
197                                     struct attribute *attr,
198                                     const char *buffer, size_t count)
199 {
200         struct obd_device *obd = container_of(kobj, struct obd_device,
201                                               obd_kset.kobj);
202         int val;
203         int rc;
204
205         rc = kstrtoint(buffer, 10, &val);
206         if (rc)
207                 return rc;
208
209         if (val < 0)
210                 return -EINVAL;
211         obd->obd_grant_check_threshold = val;
212         return count;
213 }
214 EXPORT_SYMBOL(grant_check_threshold_store);
215
216 static int obd_export_flags2str(struct obd_export *exp, struct seq_file *m)
217 {
218         bool first = true;
219
220         flag2str(exp, failed);
221         flag2str(exp, in_recovery);
222         flag2str(exp, disconnected);
223         flag2str(exp, connecting);
224         flag2str(exp, no_recovery);
225
226         return 0;
227 }
228
229 static int
230 lprocfs_exp_print_export_seq(struct obd_export *exp, void *cb_data)
231 {
232         struct seq_file         *m = cb_data;
233         struct obd_device       *obd;
234         struct obd_connect_data *ocd;
235
236         LASSERT(exp != NULL);
237         if (exp->exp_nid_stats == NULL)
238                 goto out;
239         obd = exp->exp_obd;
240         ocd = &exp->exp_connect_data;
241
242         seq_printf(m, "%s:\n"
243                    "    name: %s\n"
244                    "    client: %s\n"
245                    "    connect_flags: [ ",
246                    obd_uuid2str(&exp->exp_client_uuid),
247                    obd->obd_name,
248                    obd_export_nid2str(exp));
249         obd_connect_seq_flags2str(m, ocd->ocd_connect_flags,
250                                   ocd->ocd_connect_flags2, ", ");
251         seq_printf(m, " ]\n");
252         obd_connect_data_seqprint(m, ocd);
253         seq_printf(m, "    export_flags: [ ");
254         obd_export_flags2str(exp, m);
255         seq_printf(m, " ]\n");
256
257         if (obd->obd_type &&
258             strcmp(obd->obd_type->typ_name, "obdfilter") == 0) {
259                 struct filter_export_data *fed = &exp->exp_filter_data;
260
261                 seq_printf(m, "    grant:\n");
262                 seq_printf(m, "       granted: %ld\n",
263                         fed->fed_ted.ted_grant);
264                 seq_printf(m, "       dirty: %ld\n",
265                         fed->fed_ted.ted_dirty);
266                 seq_printf(m, "       pending: %ld\n",
267                         fed->fed_ted.ted_pending);
268         }
269
270 out:
271         return 0;
272 }
273
274 /**
275  * RPC connections are composed of an import and an export. Using the
276  * lctl utility we can extract important information about the state.
277  * The lprocfs_exp_export_seq_show routine displays the state information
278  * for the export.
279  *
280  * \param[in] m         seq file
281  * \param[in] data      unused
282  *
283  * \retval              0 on success
284  *
285  * The format of the export state information is like:
286  * a793e354-49c0-aa11-8c4f-a4f2b1a1a92b:
287  *     name: MGS
288  *     client: 10.211.55.10@tcp
289  *     connect_flags: [ version, barrier, adaptive_timeouts, ... ]
290  *     connect_data:
291  *        flags: 0x2000011005002020
292  *        instance: 0
293  *        target_version: 2.10.51.0
294  *        export_flags: [ ... ]
295  *
296  */
297 static int lprocfs_exp_export_seq_show(struct seq_file *m, void *data)
298 {
299         struct nid_stat *stats = m->private;
300
301         return obd_nid_export_for_each(stats->nid_obd, &stats->nid,
302                                        lprocfs_exp_print_export_seq, m);
303 }
304 LPROC_SEQ_FOPS_RO(lprocfs_exp_export);
305
306 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
307 {
308         CDEBUG(D_CONFIG, "stat %p - data %p/%p\n", client_stat,
309                client_stat->nid_proc, client_stat->nid_stats);
310
311         LASSERTF(atomic_read(&client_stat->nid_exp_ref_count) == 0,
312                  "nid %s:count %d\n", libcfs_nidstr(&client_stat->nid),
313                  atomic_read(&client_stat->nid_exp_ref_count));
314
315         if (client_stat->nid_proc)
316                 lprocfs_remove(&client_stat->nid_proc);
317
318         if (client_stat->nid_stats)
319                 lprocfs_stats_free(&client_stat->nid_stats);
320
321         if (client_stat->nid_ldlm_stats)
322                 lprocfs_stats_free(&client_stat->nid_ldlm_stats);
323
324         OBD_FREE_PTR(client_stat);
325 }
326
327 void lprocfs_free_per_client_stats(struct obd_device *obd)
328 {
329         struct cfs_hash *hash = obd->obd_nid_stats_hash;
330         struct nid_stat *stat;
331         ENTRY;
332
333         /* we need extra list - because hash_exit called to early */
334         /* not need locking because all clients is died */
335         while (!list_empty(&obd->obd_nid_stats)) {
336                 stat = list_first_entry(&obd->obd_nid_stats,
337                                         struct nid_stat, nid_list);
338                 list_del_init(&stat->nid_list);
339                 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
340                 lprocfs_free_client_stats(stat);
341         }
342         EXIT;
343 }
344 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
345
346 static int
347 lprocfs_exp_print_nodemap_seq(struct obd_export *exp, void *cb_data)
348 {
349         struct lu_nodemap *nodemap = exp->exp_target_data.ted_nodemap;
350         struct seq_file *m = cb_data;
351
352         if (nodemap)
353                 seq_printf(m, "%s\n", nodemap->nm_name);
354         return 0;
355 }
356
357 static int
358 lprocfs_exp_nodemap_seq_show(struct seq_file *m, void *data)
359 {
360         struct nid_stat *stats = m->private;
361
362         return obd_nid_export_for_each(stats->nid_obd, &stats->nid,
363                                        lprocfs_exp_print_nodemap_seq, m);
364 }
365 LPROC_SEQ_FOPS_RO(lprocfs_exp_nodemap);
366
367 static int
368 lprocfs_exp_print_uuid_seq(struct obd_export *exp, void *cb_data)
369 {
370         struct seq_file *m = cb_data;
371
372         if (exp->exp_nid_stats)
373                 seq_printf(m, "%s\n", obd_uuid2str(&exp->exp_client_uuid));
374         return 0;
375 }
376
377 static int lprocfs_exp_uuid_seq_show(struct seq_file *m, void *data)
378 {
379         struct nid_stat *stats = m->private;
380
381         return obd_nid_export_for_each(stats->nid_obd, &stats->nid,
382                                        lprocfs_exp_print_uuid_seq, m);
383 }
384 LPROC_SEQ_FOPS_RO(lprocfs_exp_uuid);
385
386 #define HASH_NAME_LEN   16
387
388 static void ldebugfs_rhash_seq_show(const char *name, struct rhashtable *ht,
389                                     struct seq_file *m)
390 {
391         unsigned int max_size = ht->p.max_size ? ht->p.max_size : UINT_MAX;
392         struct bucket_table *tbl;
393         int dist[8] = { 0, };
394         int maxdep = 0;
395         int i;
396
397         rcu_read_lock();
398         tbl = rht_dereference(ht->tbl, ht);
399         for (i = 0; i < tbl->size; i++) {
400                 struct rhash_head *pos;
401                 int count = 0;
402
403                 rht_for_each(pos, tbl, i)
404                         count++;
405
406                 if (count)
407                         maxdep = max(maxdep, count);
408
409                 dist[min(fls(count), 7)]++;
410         }
411
412         seq_printf(m, "%-*s %5d %5d %10u %d.%03d 0.300 0.750 0x%03x %7d %7d %7d ",
413                    HASH_NAME_LEN, name, tbl->size, ht->p.min_size, max_size,
414                    atomic_read(&ht->nelems) / tbl->size,
415                    atomic_read(&ht->nelems) * 1000 / tbl->size,
416                    ht->p.automatic_shrinking, 0,
417                    atomic_read(&ht->nelems), maxdep);
418         rcu_read_unlock();
419
420         for (i = 0; i < 8; i++)
421                 seq_printf(m, "%d%c",  dist[i], (i == 7) ? '\n' : '/');
422 }
423
424 static int
425 lprocfs_exp_print_hash_seq(struct obd_export *exp, void *cb_data)
426
427 {
428         struct obd_device *obd = exp->exp_obd;
429         struct seq_file *m = cb_data;
430
431         if (exp->exp_lock_hash != NULL) {
432                 seq_printf(m, "%-*s   cur   min        max theta t-min t-max flags rehash   count distribution\n",
433                            HASH_NAME_LEN, "name");
434                 ldebugfs_rhash_seq_show("NID_HASH", &obd->obd_nid_hash.ht, m);
435         }
436         return 0;
437 }
438
439 static int lprocfs_exp_hash_seq_show(struct seq_file *m, void *data)
440 {
441         struct nid_stat *stats = m->private;
442
443         return obd_nid_export_for_each(stats->nid_obd, &stats->nid,
444                                        lprocfs_exp_print_hash_seq, m);
445 }
446 LPROC_SEQ_FOPS_RO(lprocfs_exp_hash);
447
448 static int lprocfs_exp_print_replydata_seq(struct obd_export *exp,
449                                            void *cb_data)
450
451 {
452         struct seq_file *m = cb_data;
453         struct tg_export_data *ted = &exp->exp_target_data;
454
455         seq_printf(m, "reply_cnt: %d\n"
456                    "reply_max: %d\n"
457                    "reply_released_by_xid: %d\n"
458                    "reply_released_by_tag: %d\n\n",
459                    ted->ted_reply_cnt,
460                    ted->ted_reply_max,
461                    ted->ted_release_xid,
462                    ted->ted_release_tag);
463         return 0;
464 }
465
466 static int lprocfs_exp_replydata_seq_show(struct seq_file *m, void *data)
467 {
468         struct nid_stat *stats = m->private;
469
470         return obd_nid_export_for_each(stats->nid_obd, &stats->nid,
471                                        lprocfs_exp_print_replydata_seq, m);
472 }
473 LPROC_SEQ_FOPS_RO(lprocfs_exp_replydata);
474
475 static int lprocfs_exp_print_fmd_count_seq(struct obd_export *exp,
476                                            void *cb_data)
477 {
478         struct seq_file *m = cb_data;
479         struct tg_export_data *ted = &exp->exp_target_data;
480
481         seq_printf(m, "%d\n", ted->ted_fmd_count);
482
483         return 0;
484 }
485
486 static int lprocfs_exp_fmd_count_seq_show(struct seq_file *m, void *data)
487 {
488         struct nid_stat *stats = m->private;
489
490         return obd_nid_export_for_each(stats->nid_obd, &stats->nid,
491                                        lprocfs_exp_print_fmd_count_seq, m);
492 }
493 LPROC_SEQ_FOPS_RO(lprocfs_exp_fmd_count);
494
495 int lprocfs_nid_stats_clear_seq_show(struct seq_file *m, void *data)
496 {
497         seq_puts(m, "Write into this file to clear all nid stats and stale nid entries\n");
498         return 0;
499 }
500 EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_show);
501
502 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
503 {
504         struct nid_stat *stat = obj;
505         ENTRY;
506
507         CDEBUG(D_INFO, "refcnt %d\n", atomic_read(&stat->nid_exp_ref_count));
508         if (atomic_read(&stat->nid_exp_ref_count) == 1) {
509                 /* object has only hash references. */
510                 spin_lock(&stat->nid_obd->obd_nid_lock);
511                 list_move(&stat->nid_list, data);
512                 spin_unlock(&stat->nid_obd->obd_nid_lock);
513                 RETURN(1);
514         }
515         /* we has reference to object - only clear data*/
516         if (stat->nid_stats)
517                 lprocfs_stats_clear(stat->nid_stats);
518
519         RETURN(0);
520 }
521
522 ssize_t
523 lprocfs_nid_stats_clear_seq_write(struct file *file, const char __user *buffer,
524                                         size_t count, loff_t *off)
525 {
526         struct seq_file *m = file->private_data;
527         struct obd_device *obd = m->private;
528         struct nid_stat *client_stat;
529         LIST_HEAD(free_list);
530
531         cfs_hash_cond_del(obd->obd_nid_stats_hash,
532                           lprocfs_nid_stats_clear_write_cb, &free_list);
533
534         while (!list_empty(&free_list)) {
535                 client_stat = list_first_entry(&free_list, struct nid_stat,
536                                                nid_list);
537                 list_del_init(&client_stat->nid_list);
538                 lprocfs_free_client_stats(client_stat);
539         }
540         return count;
541 }
542 EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_write);
543
544 int lprocfs_exp_setup(struct obd_export *exp, struct lnet_nid *nid)
545 {
546         struct nid_stat *new_stat, *old_stat;
547         struct obd_device *obd = NULL;
548         struct proc_dir_entry *entry;
549         char nidstr[LNET_NIDSTR_SIZE];
550         int rc = 0;
551         ENTRY;
552
553         if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
554             !exp->exp_obd->obd_nid_stats_hash)
555                 RETURN(-EINVAL);
556
557         /* not test against zero because eric say:
558          * You may only test nid against another nid, or LNET_NID_ANY.
559          * Anything else is nonsense.*/
560         if (nid == NULL || LNET_NID_IS_ANY(nid))
561                 RETURN(-EALREADY);
562
563         libcfs_nidstr_r(nid, nidstr, sizeof(nidstr));
564
565         spin_lock(&exp->exp_lock);
566         if (exp->exp_nid_stats != NULL) {
567                 spin_unlock(&exp->exp_lock);
568                 RETURN(-EALREADY);
569         }
570         spin_unlock(&exp->exp_lock);
571
572         obd = exp->exp_obd;
573
574         CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
575
576         OBD_ALLOC_PTR(new_stat);
577         if (new_stat == NULL)
578                 RETURN(-ENOMEM);
579
580         new_stat->nid = *nid;
581         new_stat->nid_obd = exp->exp_obd;
582         /* we need set default refcount to 1 to balance obd_disconnect */
583         atomic_set(&new_stat->nid_exp_ref_count, 1);
584
585         old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
586                                            &new_stat->nid,
587                                            &new_stat->nid_hash);
588         CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
589                old_stat, nidstr, atomic_read(&old_stat->nid_exp_ref_count));
590
591         /* Return -EALREADY here so that we know that the /proc
592          * entry already has been created */
593         if (old_stat != new_stat) {
594                 spin_lock(&exp->exp_lock);
595                 if (exp->exp_nid_stats) {
596                         LASSERT(exp->exp_nid_stats == old_stat);
597                         nidstat_putref(exp->exp_nid_stats);
598                 }
599                 exp->exp_nid_stats = old_stat;
600                 spin_unlock(&exp->exp_lock);
601                 GOTO(destroy_new, rc = -EALREADY);
602         }
603         /* not found - create */
604         new_stat->nid_proc = lprocfs_register(nidstr,
605                                               obd->obd_proc_exports_entry,
606                                               NULL, NULL);
607
608         if (IS_ERR(new_stat->nid_proc)) {
609                 rc = PTR_ERR(new_stat->nid_proc);
610                 new_stat->nid_proc = NULL;
611                 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
612                        obd->obd_name, nidstr, rc);
613                 GOTO(destroy_new_ns, rc);
614         }
615
616         entry = lprocfs_add_simple(new_stat->nid_proc, "nodemap", new_stat,
617                                    &lprocfs_exp_nodemap_fops);
618         if (IS_ERR(entry)) {
619                 rc = PTR_ERR(entry);
620                 CWARN("%s: error adding the nodemap file: rc = %d\n",
621                       obd->obd_name, rc);
622                 GOTO(destroy_new_ns, rc);
623         }
624
625         entry = lprocfs_add_simple(new_stat->nid_proc, "uuid", new_stat,
626                                    &lprocfs_exp_uuid_fops);
627         if (IS_ERR(entry)) {
628                 rc = PTR_ERR(entry);
629                 CWARN("%s: error adding the NID stats file: rc = %d\n",
630                       obd->obd_name, rc);
631                 GOTO(destroy_new_ns, rc);
632         }
633
634         entry = lprocfs_add_simple(new_stat->nid_proc, "hash", new_stat,
635                                    &lprocfs_exp_hash_fops);
636         if (IS_ERR(entry)) {
637                 rc = PTR_ERR(entry);
638                 CWARN("%s: error adding the hash file: rc = %d\n",
639                       obd->obd_name, rc);
640                 GOTO(destroy_new_ns, rc);
641         }
642
643         entry = lprocfs_add_simple(new_stat->nid_proc, "export",
644                                    new_stat, &lprocfs_exp_export_fops);
645         if (IS_ERR(entry)) {
646                 rc = PTR_ERR(entry);
647                 CWARN("%s: error adding the export file: rc = %d\n",
648                       obd->obd_name, rc);
649                 GOTO(destroy_new_ns, rc);
650         }
651
652         entry = lprocfs_add_simple(new_stat->nid_proc, "reply_data", new_stat,
653                                    &lprocfs_exp_replydata_fops);
654         if (IS_ERR(entry)) {
655                 rc = PTR_ERR(entry);
656                 CWARN("%s: error adding the reply_data file: rc = %d\n",
657                       obd->obd_name, rc);
658                 GOTO(destroy_new_ns, rc);
659         }
660
661         entry = lprocfs_add_simple(new_stat->nid_proc, "fmd_count", new_stat,
662                                    &lprocfs_exp_fmd_count_fops);
663         if (IS_ERR(entry)) {
664                 rc = PTR_ERR(entry);
665                 CWARN("%s: error adding the fmd_count file: rc = %d\n",
666                       obd->obd_name, rc);
667                 GOTO(destroy_new_ns, rc);
668         }
669
670         spin_lock(&exp->exp_lock);
671         exp->exp_nid_stats = new_stat;
672         spin_unlock(&exp->exp_lock);
673
674         /* protect competitive add to list, not need locking on destroy */
675         spin_lock(&obd->obd_nid_lock);
676         list_add(&new_stat->nid_list, &obd->obd_nid_stats);
677         spin_unlock(&obd->obd_nid_lock);
678
679         RETURN(0);
680
681 destroy_new_ns:
682         if (new_stat->nid_proc != NULL)
683                 lprocfs_remove(&new_stat->nid_proc);
684         cfs_hash_del(obd->obd_nid_stats_hash, &new_stat->nid,
685                      &new_stat->nid_hash);
686
687 destroy_new:
688         nidstat_putref(new_stat);
689         OBD_FREE_PTR(new_stat);
690         RETURN(rc);
691 }
692 EXPORT_SYMBOL(lprocfs_exp_setup);
693
694 int lprocfs_exp_cleanup(struct obd_export *exp)
695 {
696         struct nid_stat *stat = exp->exp_nid_stats;
697
698         if (!stat || !exp->exp_obd)
699                 RETURN(0);
700
701         nidstat_putref(exp->exp_nid_stats);
702         exp->exp_nid_stats = NULL;
703
704         return 0;
705 }
706
707 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned int num_stats)
708 {
709         struct lprocfs_stats *stats;
710         int rc;
711
712         LASSERT(obd->obd_stats == NULL);
713         LASSERT(obd->obd_proc_entry != NULL);
714
715         stats = lprocfs_stats_alloc(num_stats, 0);
716         if (stats == NULL)
717                 return -ENOMEM;
718
719         rc = lprocfs_stats_register(obd->obd_proc_entry, "stats", stats);
720         if (rc < 0)
721                 lprocfs_stats_free(&stats);
722         else
723                 obd->obd_stats = stats;
724
725         return rc;
726 }
727 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
728
729 void lprocfs_free_obd_stats(struct obd_device *obd)
730 {
731         if (obd->obd_stats)
732                 lprocfs_stats_free(&obd->obd_stats);
733 }
734 EXPORT_SYMBOL(lprocfs_free_obd_stats);
735
736 static void display_brw_stats(struct seq_file *seq, const char *name,
737                               const char *units, struct obd_hist_pcpu *read,
738                               struct obd_hist_pcpu *write, bool scale)
739 {
740         unsigned long read_tot, write_tot, r, w, read_cum = 0, write_cum = 0;
741         unsigned int i;
742
743         seq_printf(seq, "\n%26s read      |     write\n", " ");
744         seq_printf(seq, "%-22s %-5s %% cum %% |  %-11s %% cum %%\n",
745                    name, units, units);
746
747         read_tot = lprocfs_oh_sum_pcpu(read);
748         write_tot = lprocfs_oh_sum_pcpu(write);
749
750         if (!read_tot && !write_tot)
751                 return;
752
753         for (i = 0; i < OBD_HIST_MAX; i++) {
754                 r = lprocfs_oh_counter_pcpu(read, i);
755                 w = lprocfs_oh_counter_pcpu(write, i);
756                 read_cum += r;
757                 write_cum += w;
758                 if (read_cum == 0 && write_cum == 0)
759                         continue;
760
761                 if (!scale)
762                         seq_printf(seq, "%u", i);
763                 else if (i < 10)
764                         seq_printf(seq, "%lu", BIT(i));
765                 else if (i < 20)
766                         seq_printf(seq, "%luK", BIT(i - 10));
767                 else
768                         seq_printf(seq, "%luM", BIT(i - 20));
769
770                 seq_printf(seq, ":\t\t%10lu %3u %3u   | %4lu %3u %3u\n",
771                            r, pct(r, read_tot), pct(read_cum, read_tot),
772                            w, pct(w, write_tot), pct(write_cum, write_tot));
773
774                 if (read_cum == read_tot && write_cum == write_tot)
775                         break;
776         }
777 }
778
779 static const struct brw_stats_props brw_props[] = {
780         { .bsp_name     = "pages per bulk r/w",
781           .bsp_units    = "rpcs",
782           .bsp_scale    = true                          },
783         { .bsp_name     = "discontiguous pages",
784           .bsp_units    = "rpcs",
785           .bsp_scale    = false                         },
786         { .bsp_name     = "discontiguous blocks",
787           .bsp_units    = "rpcs",
788           .bsp_scale    = false                         },
789         { .bsp_name     = "disk fragmented I/Os",
790           .bsp_units    = "ios",
791           .bsp_scale    = false                         },
792         { .bsp_name     = "disk I/Os in flight",
793           .bsp_units    = "ios",
794           .bsp_scale    = false                         },
795         { .bsp_name     = "I/O time (1/1000s)",
796           .bsp_units    = "ios",
797           .bsp_scale    = true                          },
798         { .bsp_name     = "disk I/O size",
799           .bsp_units    = "ios",
800           .bsp_scale    = true                          },
801         { .bsp_name     = "block maps msec",
802           .bsp_units    = "maps",
803           .bsp_scale    = true,                         },
804 };
805
806 static int brw_stats_seq_show(struct seq_file *seq, void *v)
807 {
808         struct brw_stats *brw_stats = seq->private;
809         int i;
810
811         /* this sampling races with updates */
812         lprocfs_stats_header(seq, ktime_get_real(), brw_stats->bs_init, 25,
813                              ":", true, "");
814
815         for (i = 0; i < ARRAY_SIZE(brw_stats->bs_props); i++) {
816                 if (!brw_stats->bs_props[i].bsp_name)
817                         continue;
818
819                 display_brw_stats(seq, brw_stats->bs_props[i].bsp_name,
820                                   brw_stats->bs_props[i].bsp_units,
821                                   &brw_stats->bs_hist[i * 2],
822                                   &brw_stats->bs_hist[i * 2 + 1],
823                                   brw_stats->bs_props[i].bsp_scale);
824         }
825
826         return 0;
827 }
828
829 static ssize_t brw_stats_seq_write(struct file *file,
830                                    const char __user *buf,
831                                    size_t len, loff_t *off)
832 {
833         struct seq_file *seq = file->private_data;
834         struct brw_stats *brw_stats = seq->private;
835         int i;
836
837         for (i = 0; i < BRW_RW_STATS_NUM; i++)
838                 lprocfs_oh_clear_pcpu(&brw_stats->bs_hist[i]);
839         brw_stats->bs_init = ktime_get_real();
840
841         return len;
842 }
843
844 LDEBUGFS_SEQ_FOPS(brw_stats);
845
846 int lprocfs_init_brw_stats(struct brw_stats *brw_stats)
847 {
848         int i, result;
849
850         for (i = 0; i < BRW_RW_STATS_NUM; i++) {
851                 result = lprocfs_oh_alloc_pcpu(&brw_stats->bs_hist[i]);
852                 if (result)
853                         break;
854         }
855
856         return result;
857 }
858 EXPORT_SYMBOL(lprocfs_init_brw_stats);
859
860 void lprocfs_fini_brw_stats(struct brw_stats *brw_stats)
861 {
862         int i;
863
864         for (i = 0; i < BRW_RW_STATS_NUM; i++)
865                 lprocfs_oh_release_pcpu(&brw_stats->bs_hist[i]);
866 }
867 EXPORT_SYMBOL(lprocfs_fini_brw_stats);
868
869 void ldebugfs_register_osd_stats(struct dentry *parent,
870                                  struct brw_stats *brw_stats,
871                                  struct lprocfs_stats *stats)
872 {
873         int i;
874
875         LASSERT(brw_stats);
876         brw_stats->bs_init = ktime_get_real();
877         for (i = 0; i < BRW_RW_STATS_NUM; i++) {
878                 struct brw_stats_props *props = brw_stats->bs_props;
879
880                 if (i % 2) {
881                         props[i / 2].bsp_name = brw_props[i / 2].bsp_name;
882                         props[i / 2].bsp_units = brw_props[i / 2].bsp_units;
883                         props[i / 2].bsp_scale = brw_props[i / 2].bsp_scale;
884                 }
885         }
886
887         if (!parent)
888                 return;
889
890         debugfs_create_file("brw_stats", 0644, parent, brw_stats,
891                             &brw_stats_fops);
892
893         if (stats)
894                 debugfs_create_file("stats", 0644, parent, stats,
895                                     &ldebugfs_stats_seq_fops);
896 }
897 EXPORT_SYMBOL(ldebugfs_register_osd_stats);
898
899 int lprocfs_hash_seq_show(struct seq_file *m, void *data)
900 {
901         struct obd_device *obd = m->private;
902
903         if (obd == NULL)
904                 return 0;
905
906         /* header for rhashtable state */
907         seq_printf(m, "%-*s   cur   min        max theta t-min t-max flags  rehash   count  maxdep distribution\n",
908                    HASH_NAME_LEN, "name");
909         ldebugfs_rhash_seq_show("UUID_HASH", &obd->obd_uuid_hash, m);
910         ldebugfs_rhash_seq_show("NID_HASH", &obd->obd_nid_hash.ht, m);
911
912         cfs_hash_debug_header(m);
913         cfs_hash_debug_str(obd->obd_nid_stats_hash, m);
914         return 0;
915 }
916 EXPORT_SYMBOL(lprocfs_hash_seq_show);
917
918 int lprocfs_recovery_status_seq_show(struct seq_file *m, void *data)
919 {
920         struct obd_device *obd = m->private;
921         struct target_distribute_txn_data *tdtd;
922
923         LASSERT(obd != NULL);
924
925         seq_printf(m, "status: ");
926         if (atomic_read(&obd->obd_max_recoverable_clients) == 0) {
927                 seq_printf(m, "INACTIVE\n");
928                 goto out;
929         }
930
931         /* There is gap between client data read from storage and setting
932          * obd_recovering so check obd_recovery_end as well to make sure
933          * recovery is really finished
934          */
935         if (obd->obd_recovery_end > 0 && !obd->obd_recovering) {
936                 seq_printf(m, "COMPLETE\n");
937                 seq_printf(m, "recovery_start: %lld\n",
938                            (s64)ktime_get_real_seconds() -
939                            (ktime_get_seconds() - obd->obd_recovery_start));
940                 seq_printf(m, "recovery_duration: %lld\n",
941                            obd->obd_recovery_end ?
942                            obd->obd_recovery_end - obd->obd_recovery_start :
943                            ktime_get_seconds() - obd->obd_recovery_start);
944                 /* Number of clients that have completed recovery */
945                 seq_printf(m, "completed_clients: %d/%d\n",
946                            atomic_read(&obd->obd_max_recoverable_clients) -
947                            obd->obd_stale_clients,
948                            atomic_read(&obd->obd_max_recoverable_clients));
949                 seq_printf(m, "replayed_requests: %d\n",
950                            obd->obd_replayed_requests);
951                 seq_printf(m, "last_transno: %lld\n",
952                            obd->obd_next_recovery_transno - 1);
953                 seq_printf(m, "VBR: %s\n", obd->obd_version_recov ?
954                            "ENABLED" : "DISABLED");
955                 seq_printf(m, "IR: %s\n", obd->obd_no_ir ?
956                            "DISABLED" : "ENABLED");
957                 goto out;
958         }
959
960         tdtd = obd2obt(obd)->obt_lut->lut_tdtd;
961         if (tdtd && tdtd->tdtd_show_update_logs_retrievers) {
962                 char *buf;
963                 int size = 0;
964                 int count = 0;
965
966                 buf = tdtd->tdtd_show_update_logs_retrievers(
967                         tdtd->tdtd_show_retrievers_cbdata,
968                         &size, &count);
969                 if (count > 0) {
970                         seq_printf(m, "WAITING\n");
971                         seq_printf(m, "non-ready MDTs: %s\n",
972                                    buf ? buf : "unknown (not enough RAM)");
973                         seq_printf(m, "recovery_start: %lld\n",
974                                    (s64)ktime_get_real_seconds() -
975                                    (ktime_get_seconds() -
976                                     obd->obd_recovery_start));
977                         seq_printf(m, "time_waited: %lld\n",
978                                    (s64)(ktime_get_seconds() -
979                                          obd->obd_recovery_start));
980                 }
981
982                 if (buf != NULL)
983                         OBD_FREE(buf, size);
984
985                 if (likely(count > 0))
986                         goto out;
987         }
988
989         /* recovery won't start until the clients connect */
990         if (obd->obd_recovery_start == 0) {
991                 seq_printf(m, "WAITING_FOR_CLIENTS\n");
992                 goto out;
993         }
994
995         seq_printf(m, "RECOVERING\n");
996         seq_printf(m, "recovery_start: %lld\n", (s64)ktime_get_real_seconds() -
997                    (ktime_get_seconds() - obd->obd_recovery_start));
998         seq_printf(m, "time_remaining: %lld\n",
999                    ktime_get_seconds() >=
1000                    obd->obd_recovery_start +
1001                    obd->obd_recovery_timeout ? 0 :
1002                    (s64)(obd->obd_recovery_start +
1003                          obd->obd_recovery_timeout -
1004                          ktime_get_seconds()));
1005         seq_printf(m, "connected_clients: %d/%d\n",
1006                    atomic_read(&obd->obd_connected_clients),
1007                    atomic_read(&obd->obd_max_recoverable_clients));
1008         /* Number of clients that have completed recovery */
1009         seq_printf(m, "req_replay_clients: %d\n",
1010                    atomic_read(&obd->obd_req_replay_clients));
1011         seq_printf(m, "lock_repay_clients: %d\n",
1012                    atomic_read(&obd->obd_lock_replay_clients));
1013         seq_printf(m, "completed_clients: %d\n",
1014                    atomic_read(&obd->obd_connected_clients) -
1015                    atomic_read(&obd->obd_lock_replay_clients));
1016         seq_printf(m, "evicted_clients: %d\n", obd->obd_stale_clients);
1017         seq_printf(m, "replayed_requests: %d\n", obd->obd_replayed_requests);
1018         seq_printf(m, "queued_requests: %d\n",
1019                    obd->obd_requests_queued_for_recovery);
1020         seq_printf(m, "next_transno: %lld\n",
1021                    obd->obd_next_recovery_transno);
1022 out:
1023         return 0;
1024 }
1025 EXPORT_SYMBOL(lprocfs_recovery_status_seq_show);
1026
1027 ssize_t ir_factor_show(struct kobject *kobj, struct attribute *attr,
1028                        char *buf)
1029 {
1030         struct obd_device *obd = container_of(kobj, struct obd_device,
1031                                               obd_kset.kobj);
1032
1033         return scnprintf(buf, PAGE_SIZE, "%d\n", obd->obd_recovery_ir_factor);
1034 }
1035 EXPORT_SYMBOL(ir_factor_show);
1036
1037 ssize_t ir_factor_store(struct kobject *kobj, struct attribute *attr,
1038                         const char *buffer, size_t count)
1039 {
1040         struct obd_device *obd = container_of(kobj, struct obd_device,
1041                                               obd_kset.kobj);
1042         int val;
1043         int rc;
1044
1045         rc = kstrtoint(buffer, 10, &val);
1046         if (rc)
1047                 return rc;
1048
1049         if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
1050                 return -EINVAL;
1051
1052         obd->obd_recovery_ir_factor = val;
1053         return count;
1054 }
1055 EXPORT_SYMBOL(ir_factor_store);
1056
1057 int lprocfs_checksum_dump_seq_show(struct seq_file *m, void *data)
1058 {
1059         struct obd_device *obd = m->private;
1060
1061         LASSERT(obd != NULL);
1062         seq_printf(m, "%d\n", obd->obd_checksum_dump);
1063         return 0;
1064 }
1065 EXPORT_SYMBOL(lprocfs_checksum_dump_seq_show);
1066
1067 ssize_t
1068 lprocfs_checksum_dump_seq_write(struct file *file, const char __user *buffer,
1069                             size_t count, loff_t *off)
1070 {
1071         struct seq_file *m = file->private_data;
1072         struct obd_device *obd = m->private;
1073         bool val;
1074         int rc;
1075
1076         LASSERT(obd != NULL);
1077         rc = kstrtobool_from_user(buffer, count, &val);
1078         if (rc)
1079                 return rc;
1080
1081         obd->obd_checksum_dump = val;
1082         return count;
1083 }
1084 EXPORT_SYMBOL(lprocfs_checksum_dump_seq_write);
1085
1086 ssize_t recovery_time_soft_show(struct kobject *kobj, struct attribute *attr,
1087                                 char *buf)
1088 {
1089         struct obd_device *obd = container_of(kobj, struct obd_device,
1090                                               obd_kset.kobj);
1091
1092         return scnprintf(buf, PAGE_SIZE, "%d\n", obd->obd_recovery_timeout);
1093 }
1094 EXPORT_SYMBOL(recovery_time_soft_show);
1095
1096 ssize_t recovery_time_soft_store(struct kobject *kobj,
1097                                  struct attribute *attr,
1098                                  const char *buffer, size_t count)
1099 {
1100         struct obd_device *obd = container_of(kobj, struct obd_device,
1101                                               obd_kset.kobj);
1102         unsigned int val;
1103         int rc;
1104
1105         rc = kstrtouint(buffer, 0, &val);
1106         if (rc)
1107                 return rc;
1108
1109         obd->obd_recovery_timeout = val;
1110         return count;
1111 }
1112 EXPORT_SYMBOL(recovery_time_soft_store);
1113
1114 ssize_t recovery_time_hard_show(struct kobject *kobj, struct attribute *attr,
1115                                 char *buf)
1116 {
1117         struct obd_device *obd = container_of(kobj, struct obd_device,
1118                                               obd_kset.kobj);
1119
1120         return scnprintf(buf, PAGE_SIZE, "%d\n", obd->obd_recovery_time_hard);
1121 }
1122 EXPORT_SYMBOL(recovery_time_hard_show);
1123
1124 ssize_t recovery_time_hard_store(struct kobject *kobj,
1125                                  struct attribute *attr,
1126                                  const char *buffer, size_t count)
1127 {
1128         struct obd_device *obd = container_of(kobj, struct obd_device,
1129                                               obd_kset.kobj);
1130         unsigned int val;
1131         int rc;
1132
1133         rc = kstrtouint(buffer, 0, &val);
1134         if (rc)
1135                 return rc;
1136
1137         obd->obd_recovery_time_hard = val;
1138         return count;
1139 }
1140 EXPORT_SYMBOL(recovery_time_hard_store);
1141
1142 ssize_t instance_show(struct kobject *kobj, struct attribute *attr,
1143                       char *buf)
1144 {
1145         struct obd_device *obd = container_of(kobj, struct obd_device,
1146                                               obd_kset.kobj);
1147         struct obd_device_target *target = obd2obt(obd);
1148
1149         LASSERT(target->obt_magic == OBT_MAGIC);
1150         return scnprintf(buf, PAGE_SIZE, "%u\n", obd2obt(obd)->obt_instance);
1151 }
1152 EXPORT_SYMBOL(instance_show);
1153
1154 #endif /* CONFIG_PROC_FS*/