4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
23 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Use is subject to license terms.
26 * Copyright (c) 2011, 2013, Intel Corporation.
29 * This file is part of Lustre, http://www.lustre.org/
30 * Lustre is a trademark of Sun Microsystems, Inc.
32 * lustre/obdclass/lprocfs_status_server.c
35 #define DEBUG_SUBSYSTEM S_CLASS
38 #include <liblustre.h>
41 #include <obd_class.h>
42 #include <lprocfs_status.h>
43 #include <lustre/lustre_idl.h>
47 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
49 struct obd_device *obd = PDE_DATA(f->f_dentry->d_inode);
51 atomic_inc(&obd->obd_evict_inprogress);
55 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
57 struct obd_device *obd = PDE_DATA(f->f_dentry->d_inode);
59 atomic_dec(&obd->obd_evict_inprogress);
60 wake_up(&obd->obd_evict_inprogress_waitq);
65 #define BUFLEN (UUID_MAX + 5)
68 lprocfs_evict_client_seq_write(struct file *file, const char *buffer,
69 size_t count, loff_t *off)
71 struct seq_file *m = file->private_data;
72 struct obd_device *obd = m->private;
75 OBD_ALLOC(kbuf, BUFLEN);
80 * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1
81 * bytes into kbuf, to ensure that the string is NUL-terminated.
82 * UUID_MAX should include a trailing NUL already.
84 if (copy_from_user(kbuf, buffer,
85 min_t(unsigned long, BUFLEN - 1, count))) {
89 tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count));
90 class_incref(obd, __func__, current);
92 if (strncmp(tmpbuf, "nid:", 4) == 0)
93 obd_export_evict_by_nid(obd, tmpbuf + 4);
94 else if (strncmp(tmpbuf, "uuid:", 5) == 0)
95 obd_export_evict_by_uuid(obd, tmpbuf + 5);
97 obd_export_evict_by_uuid(obd, tmpbuf);
99 class_decref(obd, __func__, current);
102 OBD_FREE(kbuf, BUFLEN);
105 EXPORT_SYMBOL(lprocfs_evict_client_seq_write);
107 #ifndef HAVE_ONLY_PROCFS_SEQ
108 int lprocfs_wr_evict_client(struct file *file, const char __user *buffer,
109 unsigned long count, void *data)
111 struct obd_device *obd = data;
115 OBD_ALLOC(kbuf, BUFLEN);
120 * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1
121 * bytes into kbuf, to ensure that the string is NUL-terminated.
122 * UUID_MAX should include a trailing NUL already.
124 if (copy_from_user(kbuf, buffer,
125 min_t(unsigned long, BUFLEN - 1, count))) {
129 tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count));
130 class_incref(obd, __func__, current);
132 if (strncmp(tmpbuf, "nid:", 4) == 0)
133 obd_export_evict_by_nid(obd, tmpbuf + 4);
134 else if (strncmp(tmpbuf, "uuid:", 5) == 0)
135 obd_export_evict_by_uuid(obd, tmpbuf + 5);
137 obd_export_evict_by_uuid(obd, tmpbuf);
139 class_decref(obd, __func__, current);
141 OBD_FREE(kbuf, BUFLEN);
144 EXPORT_SYMBOL(lprocfs_wr_evict_client);
146 const struct file_operations lprocfs_evict_client_fops = {
147 .owner = THIS_MODULE,
148 .read = lprocfs_fops_read,
149 .write = lprocfs_fops_write,
150 .open = lprocfs_evict_client_open,
151 .release = lprocfs_evict_client_release,
153 EXPORT_SYMBOL(lprocfs_evict_client_fops);
155 /* Function that emulates snprintf but also has the side effect of advancing
156 the page pointer for the next write into the buffer, incrementing the total
157 length written to the buffer, and decrementing the size left in the
159 static int lprocfs_obd_snprintf(char **page, int end, int *len,
160 const char *format, ...)
168 va_start(list, format);
169 n = vsnprintf(*page, end - *len, format, list);
172 *page += n; *len += n;
175 #endif /* HAVE_ONLY_PROCFS_SEQ */
179 int lprocfs_num_exports_seq_show(struct seq_file *m, void *data)
181 struct obd_device *obd = data;
183 LASSERT(obd != NULL);
184 return seq_printf(m, "%u\n", obd->obd_num_exports);
186 EXPORT_SYMBOL(lprocfs_num_exports_seq_show);
188 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
190 CDEBUG(D_CONFIG, "stat %p - data %p/%p\n", client_stat,
191 client_stat->nid_proc, client_stat->nid_stats);
193 LASSERTF(atomic_read(&client_stat->nid_exp_ref_count) == 0,
194 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
195 atomic_read(&client_stat->nid_exp_ref_count));
197 if (client_stat->nid_proc)
198 lprocfs_remove(&client_stat->nid_proc);
200 if (client_stat->nid_stats)
201 lprocfs_free_stats(&client_stat->nid_stats);
203 if (client_stat->nid_ldlm_stats)
204 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
206 OBD_FREE_PTR(client_stat);
210 void lprocfs_free_per_client_stats(struct obd_device *obd)
212 cfs_hash_t *hash = obd->obd_nid_stats_hash;
213 struct nid_stat *stat;
216 /* we need extra list - because hash_exit called to early */
217 /* not need locking because all clients is died */
218 while (!list_empty(&obd->obd_nid_stats)) {
219 stat = list_entry(obd->obd_nid_stats.next,
220 struct nid_stat, nid_list);
221 list_del_init(&stat->nid_list);
222 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
223 lprocfs_free_client_stats(stat);
227 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
229 int lprocfs_exp_nid_seq_show(struct seq_file *m, void *data)
231 struct obd_export *exp = m->private;
232 LASSERT(exp != NULL);
233 return seq_printf(m, "%s\n", obd_export_nid2str(exp));
236 int lprocfs_exp_print_uuid_seq(cfs_hash_t *hs, cfs_hash_bd_t *bd,
237 struct hlist_node *hnode, void *cb_data)
240 struct obd_export *exp = cfs_hash_object(hs, hnode);
241 struct seq_file *m = cb_data;
243 if (exp->exp_nid_stats)
244 seq_printf(m, "%s\n", obd_uuid2str(&exp->exp_client_uuid));
248 int lprocfs_exp_uuid_seq_show(struct seq_file *m, void *data)
250 struct nid_stat *stats = m->private;
251 struct obd_device *obd = stats->nid_obd;
253 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
254 lprocfs_exp_print_uuid_seq, m);
257 LPROC_SEQ_FOPS_RO(lprocfs_exp_uuid);
259 int lprocfs_exp_print_hash_seq(cfs_hash_t *hs, cfs_hash_bd_t *bd,
260 struct hlist_node *hnode, void *cb_data)
263 struct seq_file *m = cb_data;
264 struct obd_export *exp = cfs_hash_object(hs, hnode);
266 if (exp->exp_lock_hash != NULL) {
267 cfs_hash_debug_header_seq(m);
268 cfs_hash_debug_str_seq(hs, m);
273 int lprocfs_exp_hash_seq_show(struct seq_file *m, void *data)
275 struct nid_stat *stats = m->private;
276 struct obd_device *obd = stats->nid_obd;
278 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
279 lprocfs_exp_print_hash_seq, m);
282 LPROC_SEQ_FOPS_RO(lprocfs_exp_hash);
284 int lprocfs_nid_stats_clear_seq_show(struct seq_file *m, void *data)
286 return seq_printf(m, "%s\n", "Write into this file to clear all nid "
287 "stats and stale nid entries");
289 EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_show);
291 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
293 struct nid_stat *stat = obj;
296 CDEBUG(D_INFO, "refcnt %d\n", atomic_read(&stat->nid_exp_ref_count));
297 if (atomic_read(&stat->nid_exp_ref_count) == 1) {
298 /* object has only hash references. */
299 spin_lock(&stat->nid_obd->obd_nid_lock);
300 list_move(&stat->nid_list, data);
301 spin_unlock(&stat->nid_obd->obd_nid_lock);
304 /* we has reference to object - only clear data*/
306 lprocfs_clear_stats(stat->nid_stats);
312 lprocfs_nid_stats_clear_seq_write(struct file *file, const char *buffer,
313 size_t count, loff_t *off)
315 struct list_head free_list = LIST_HEAD_INIT(free_list);
316 struct seq_file *m = file->private_data;
317 struct obd_device *obd = m->private;
318 struct nid_stat *client_stat;
320 cfs_hash_cond_del(obd->obd_nid_stats_hash,
321 lprocfs_nid_stats_clear_write_cb, &free_list);
323 while (!list_empty(&free_list)) {
324 client_stat = list_entry(free_list.next, struct nid_stat,
326 list_del_init(&client_stat->nid_list);
327 lprocfs_free_client_stats(client_stat);
331 EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_write);
333 #ifndef HAVE_ONLY_PROCFS_SEQ
334 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
335 int *eof, void *data)
337 struct obd_device *obd = data;
339 LASSERT(obd != NULL);
341 return snprintf(page, count, "%u\n", obd->obd_num_exports);
343 EXPORT_SYMBOL(lprocfs_rd_num_exports);
345 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
346 int *eof, void *data)
348 struct obd_export *exp = data;
349 LASSERT(exp != NULL);
351 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
354 struct exp_uuid_cb_data {
362 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
363 int count, int *eof, int *len)
365 cb_data->page = page;
366 cb_data->count = count;
371 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
372 struct hlist_node *hnode, void *cb_data)
375 struct obd_export *exp = cfs_hash_object(hs, hnode);
376 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
378 if (exp->exp_nid_stats)
379 *data->len += snprintf((data->page + *data->len),
381 obd_uuid2str(&exp->exp_client_uuid));
385 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
386 int *eof, void *data)
388 struct nid_stat *stats = (struct nid_stat *)data;
389 struct exp_uuid_cb_data cb_data;
390 struct obd_device *obd = stats->nid_obd;
395 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
396 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
397 lprocfs_exp_print_uuid, &cb_data);
401 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
402 struct hlist_node *hnode, void *cb_data)
405 struct exp_uuid_cb_data *data = cb_data;
406 struct obd_export *exp = cfs_hash_object(hs, hnode);
408 if (exp->exp_lock_hash != NULL) {
410 *data->len += cfs_hash_debug_header(data->page,
413 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
419 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
420 int *eof, void *data)
422 struct nid_stat *stats = (struct nid_stat *)data;
423 struct exp_uuid_cb_data cb_data;
424 struct obd_device *obd = stats->nid_obd;
429 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
431 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
432 lprocfs_exp_print_hash, &cb_data);
436 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
437 int count, int *eof, void *data)
440 return snprintf(page, count, "%s\n",
441 "Write into this file to clear all nid stats and "
442 "stale nid entries");
444 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
446 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
447 unsigned long count, void *data)
449 struct list_head free_list = LIST_HEAD_INIT(free_list);
450 struct obd_device *obd = (struct obd_device *)data;
451 struct nid_stat *client_stat;
453 cfs_hash_cond_del(obd->obd_nid_stats_hash,
454 lprocfs_nid_stats_clear_write_cb, &free_list);
456 while (!list_empty(&free_list)) {
457 client_stat = list_entry(free_list.next, struct nid_stat,
459 list_del_init(&client_stat->nid_list);
460 lprocfs_free_client_stats(client_stat);
465 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
468 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
470 struct nid_stat *new_stat, *old_stat;
471 struct obd_device *obd = NULL;
472 struct proc_dir_entry *entry;
479 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
480 !exp->exp_obd->obd_nid_stats_hash)
483 /* not test against zero because eric say:
484 * You may only test nid against another nid, or LNET_NID_ANY.
485 * Anything else is nonsense.*/
486 if (!nid || *nid == LNET_NID_ANY)
489 spin_lock(&exp->exp_lock);
490 if (exp->exp_nid_stats != NULL) {
491 spin_unlock(&exp->exp_lock);
494 spin_unlock(&exp->exp_lock);
498 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
500 OBD_ALLOC_PTR(new_stat);
501 if (new_stat == NULL)
504 new_stat->nid = *nid;
505 new_stat->nid_obd = exp->exp_obd;
506 /* we need set default refcount to 1 to balance obd_disconnect */
507 atomic_set(&new_stat->nid_exp_ref_count, 1);
509 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
510 nid, &new_stat->nid_hash);
511 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
512 old_stat, libcfs_nid2str(*nid),
513 atomic_read(&new_stat->nid_exp_ref_count));
515 /* Return -EALREADY here so that we know that the /proc
516 * entry already has been created */
517 if (old_stat != new_stat) {
518 spin_lock(&exp->exp_lock);
519 if (exp->exp_nid_stats) {
520 LASSERT(exp->exp_nid_stats == old_stat);
521 nidstat_putref(exp->exp_nid_stats);
523 exp->exp_nid_stats = old_stat;
524 spin_unlock(&exp->exp_lock);
525 GOTO(destroy_new, rc = -EALREADY);
527 /* not found - create */
528 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
530 GOTO(destroy_new, rc = -ENOMEM);
532 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
533 #ifndef HAVE_ONLY_PROCFS_SEQ
534 new_stat->nid_proc = lprocfs_register(buffer,
535 obd->obd_proc_exports_entry,
538 new_stat->nid_proc = lprocfs_seq_register(buffer,
539 obd->obd_proc_exports_entry,
542 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
544 if (IS_ERR(new_stat->nid_proc)) {
545 rc = PTR_ERR(new_stat->nid_proc);
546 new_stat->nid_proc = NULL;
547 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
548 obd->obd_name, libcfs_nid2str(*nid), rc);
549 GOTO(destroy_new_ns, rc);
552 #ifndef HAVE_ONLY_PROCFS_SEQ
553 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
554 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
556 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid", new_stat,
557 &lprocfs_exp_uuid_fops);
560 CWARN("Error adding the NID stats file\n");
562 GOTO(destroy_new_ns, rc);
565 #ifndef HAVE_ONLY_PROCFS_SEQ
566 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
567 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
569 entry = lprocfs_add_simple(new_stat->nid_proc, "hash", new_stat,
570 &lprocfs_exp_hash_fops);
573 CWARN("Error adding the hash file\n");
575 GOTO(destroy_new_ns, rc);
578 spin_lock(&exp->exp_lock);
579 exp->exp_nid_stats = new_stat;
580 spin_unlock(&exp->exp_lock);
582 /* protect competitive add to list, not need locking on destroy */
583 spin_lock(&obd->obd_nid_lock);
584 list_add(&new_stat->nid_list, &obd->obd_nid_stats);
585 spin_unlock(&obd->obd_nid_lock);
590 if (new_stat->nid_proc != NULL)
591 lprocfs_remove(&new_stat->nid_proc);
592 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
595 nidstat_putref(new_stat);
596 OBD_FREE_PTR(new_stat);
599 EXPORT_SYMBOL(lprocfs_exp_setup);
601 int lprocfs_exp_cleanup(struct obd_export *exp)
603 struct nid_stat *stat = exp->exp_nid_stats;
605 if (!stat || !exp->exp_obd)
608 nidstat_putref(exp->exp_nid_stats);
609 exp->exp_nid_stats = NULL;
613 EXPORT_SYMBOL(lprocfs_exp_cleanup);
615 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
617 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
618 LASSERT(coffset < stats->ls_num); \
619 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
622 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
624 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
625 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
626 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
627 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
628 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
629 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
630 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
631 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
632 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
633 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
634 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
635 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
636 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
637 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
638 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
639 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
640 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
641 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
642 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
643 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
644 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
645 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
646 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
647 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
648 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
649 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
650 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
651 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
652 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
653 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
654 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
655 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
656 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
657 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
658 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
659 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
660 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
661 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
662 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
663 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
664 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
665 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
666 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
667 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
668 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
669 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
670 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
672 CLASSERT(NUM_OBD_STATS == OBD_COUNTER_OFFSET(putref) + 1);
674 EXPORT_SYMBOL(lprocfs_init_ops_stats);
676 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
678 struct lprocfs_stats *stats;
679 unsigned int num_stats;
682 LASSERT(obd->obd_stats == NULL);
683 LASSERT(obd->obd_proc_entry != NULL);
684 LASSERT(obd->obd_cntr_base == 0);
686 num_stats = NUM_OBD_STATS + num_private_stats;
687 stats = lprocfs_alloc_stats(num_stats, 0);
691 lprocfs_init_ops_stats(num_private_stats, stats);
693 for (i = num_private_stats; i < num_stats; i++) {
694 /* If this LBUGs, it is likely that an obd
695 * operation was added to struct obd_ops in
696 * <obd.h>, and that the corresponding line item
697 * LPROCFS_OBD_OP_INIT(.., .., opname)
698 * is missing from the list above. */
699 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
700 "Missing obd_stat initializer obd_op "
701 "operation at offset %d.\n", i - num_private_stats);
703 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
705 lprocfs_free_stats(&stats);
707 obd->obd_stats = stats;
708 obd->obd_cntr_base = num_private_stats;
712 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
714 void lprocfs_free_obd_stats(struct obd_device *obd)
717 lprocfs_free_stats(&obd->obd_stats);
719 EXPORT_SYMBOL(lprocfs_free_obd_stats);
721 int lprocfs_hash_seq_show(struct seq_file *m, void *data)
723 struct obd_device *obd = m->private;
729 c += cfs_hash_debug_header_seq(m);
730 c += cfs_hash_debug_str_seq(obd->obd_uuid_hash, m);
731 c += cfs_hash_debug_str_seq(obd->obd_nid_hash, m);
732 c += cfs_hash_debug_str_seq(obd->obd_nid_stats_hash, m);
735 EXPORT_SYMBOL(lprocfs_hash_seq_show);
737 int lprocfs_recovery_status_seq_show(struct seq_file *m, void *data)
739 struct obd_device *obd = m->private;
741 LASSERT(obd != NULL);
743 seq_printf(m, "status: ");
744 if (obd->obd_max_recoverable_clients == 0) {
745 seq_printf(m, "INACTIVE\n");
749 /* sampled unlocked, but really... */
750 if (obd->obd_recovering == 0) {
751 seq_printf(m, "COMPLETE\n");
752 seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start);
753 seq_printf(m, "recovery_duration: %lu\n",
754 obd->obd_recovery_end - obd->obd_recovery_start);
755 /* Number of clients that have completed recovery */
756 seq_printf(m, "completed_clients: %d/%d\n",
757 obd->obd_max_recoverable_clients -
758 obd->obd_stale_clients,
759 obd->obd_max_recoverable_clients);
760 seq_printf(m, "replayed_requests: %d\n",
761 obd->obd_replayed_requests);
762 seq_printf(m, "last_transno: "LPD64"\n",
763 obd->obd_next_recovery_transno - 1);
764 seq_printf(m, "VBR: %s\n", obd->obd_version_recov ?
765 "ENABLED" : "DISABLED");
766 seq_printf(m, "IR: %s\n", obd->obd_no_ir ?
767 "DISABLED" : "ENABLED");
771 seq_printf(m, "RECOVERING\n");
772 seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start);
773 seq_printf(m, "time_remaining: %lu\n",
774 cfs_time_current_sec() >=
775 obd->obd_recovery_start +
776 obd->obd_recovery_timeout ? 0 :
777 obd->obd_recovery_start +
778 obd->obd_recovery_timeout -
779 cfs_time_current_sec());
780 seq_printf(m, "connected_clients: %d/%d\n",
781 atomic_read(&obd->obd_connected_clients),
782 obd->obd_max_recoverable_clients);
783 /* Number of clients that have completed recovery */
784 seq_printf(m, "req_replay_clients: %d\n",
785 atomic_read(&obd->obd_req_replay_clients));
786 seq_printf(m, "lock_repay_clients: %d\n",
787 atomic_read(&obd->obd_lock_replay_clients));
788 seq_printf(m, "completed_clients: %d\n",
789 atomic_read(&obd->obd_connected_clients) -
790 atomic_read(&obd->obd_lock_replay_clients));
791 seq_printf(m, "evicted_clients: %d\n", obd->obd_stale_clients);
792 seq_printf(m, "replayed_requests: %d\n", obd->obd_replayed_requests);
793 seq_printf(m, "queued_requests: %d\n",
794 obd->obd_requests_queued_for_recovery);
795 seq_printf(m, "next_transno: "LPD64"\n",
796 obd->obd_next_recovery_transno);
800 EXPORT_SYMBOL(lprocfs_recovery_status_seq_show);
802 int lprocfs_ir_factor_seq_show(struct seq_file *m, void *data)
804 struct obd_device *obd = m->private;
806 LASSERT(obd != NULL);
807 return seq_printf(m, "%d\n", obd->obd_recovery_ir_factor);
809 EXPORT_SYMBOL(lprocfs_ir_factor_seq_show);
812 lprocfs_ir_factor_seq_write(struct file *file, const char *buffer,
813 size_t count, loff_t *off)
815 struct seq_file *m = file->private_data;
816 struct obd_device *obd = m->private;
819 LASSERT(obd != NULL);
820 rc = lprocfs_write_helper(buffer, count, &val);
824 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
827 obd->obd_recovery_ir_factor = val;
830 EXPORT_SYMBOL(lprocfs_ir_factor_seq_write);
832 int lprocfs_recovery_time_soft_seq_show(struct seq_file *m, void *data)
834 struct obd_device *obd = m->private;
836 LASSERT(obd != NULL);
837 return seq_printf(m, "%d\n", obd->obd_recovery_timeout);
839 EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_show);
842 lprocfs_recovery_time_soft_seq_write(struct file *file, const char *buffer,
843 size_t count, loff_t *off)
845 struct seq_file *m = file->private_data;
846 struct obd_device *obd = m->private;
849 LASSERT(obd != NULL);
850 rc = lprocfs_write_helper(buffer, count, &val);
854 obd->obd_recovery_timeout = val;
857 EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_write);
859 int lprocfs_recovery_time_hard_seq_show(struct seq_file *m, void *data)
861 struct obd_device *obd = m->private;
863 LASSERT(obd != NULL);
864 return seq_printf(m, "%u\n", obd->obd_recovery_time_hard);
866 EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_show);
869 lprocfs_recovery_time_hard_seq_write(struct file *file, const char *buffer,
870 size_t count, loff_t *off)
872 struct seq_file *m = file->private_data;
873 struct obd_device *obd = m->private;
876 LASSERT(obd != NULL);
877 rc = lprocfs_write_helper(buffer, count, &val);
881 obd->obd_recovery_time_hard = val;
884 EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_write);
886 int lprocfs_target_instance_seq_show(struct seq_file *m, void *data)
888 struct obd_device *obd = m->private;
889 struct obd_device_target *target = &obd->u.obt;
891 LASSERT(obd != NULL);
892 LASSERT(target->obt_magic == OBT_MAGIC);
893 return seq_printf(m, "%u\n", obd->u.obt.obt_instance);
895 EXPORT_SYMBOL(lprocfs_target_instance_seq_show);
897 #ifndef HAVE_ONLY_PROCFS_SEQ
898 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
899 int count, int *eof, void *data)
901 struct obd_device *obd = data;
907 c += cfs_hash_debug_header(page, count);
908 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
909 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
910 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
914 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
916 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
917 int count, int *eof, void *data)
919 struct obd_device *obd = data;
922 LASSERT(obd != NULL);
925 /* Set start of user data returned to
926 page + off since the user may have
927 requested to read much smaller than
928 what we need to read */
932 * We know we are allocated a page here.
933 * Also we know that this function will
934 * not need to write more than a page
935 * so we can truncate at PAGE_CACHE_SIZE.
937 size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
939 /* Initialize the page */
940 memset(page, 0, size);
942 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
944 if (obd->obd_max_recoverable_clients == 0) {
945 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
951 /* sampled unlocked, but really... */
952 if (obd->obd_recovering == 0) {
953 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
955 if (lprocfs_obd_snprintf(&page, size, &len,
956 "recovery_start: %lu\n",
957 obd->obd_recovery_start) <= 0)
959 if (lprocfs_obd_snprintf(&page, size, &len,
960 "recovery_duration: %lu\n",
961 obd->obd_recovery_end -
962 obd->obd_recovery_start) <= 0)
964 /* Number of clients that have completed recovery */
965 if (lprocfs_obd_snprintf(&page, size, &len,
966 "completed_clients: %d/%d\n",
967 obd->obd_max_recoverable_clients -
968 obd->obd_stale_clients,
969 obd->obd_max_recoverable_clients) <= 0)
971 if (lprocfs_obd_snprintf(&page, size, &len,
972 "replayed_requests: %d\n",
973 obd->obd_replayed_requests) <= 0)
975 if (lprocfs_obd_snprintf(&page, size, &len,
976 "last_transno: "LPD64"\n",
977 obd->obd_next_recovery_transno - 1) <= 0)
979 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
980 obd->obd_version_recov ?
981 "ENABLED" : "DISABLED") <= 0)
983 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
985 "DISABLED" : "ENABLED") <= 0)
990 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
992 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
993 obd->obd_recovery_start) <= 0)
995 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
996 cfs_time_current_sec() >=
997 obd->obd_recovery_start +
998 obd->obd_recovery_timeout ? 0 :
999 obd->obd_recovery_start +
1000 obd->obd_recovery_timeout -
1001 cfs_time_current_sec()) <= 0)
1003 if (lprocfs_obd_snprintf(&page, size, &len,
1004 "connected_clients: %d/%d\n",
1005 atomic_read(&obd->obd_connected_clients),
1006 obd->obd_max_recoverable_clients) <= 0)
1008 /* Number of clients that have completed recovery */
1009 if (lprocfs_obd_snprintf(&page, size, &len, "req_replay_clients: %d\n",
1010 atomic_read(&obd->obd_req_replay_clients))
1013 if (lprocfs_obd_snprintf(&page, size, &len, "lock_repay_clients: %d\n",
1014 atomic_read(&obd->obd_lock_replay_clients))
1017 if (lprocfs_obd_snprintf(&page, size, &len, "completed_clients: %d\n",
1018 atomic_read(&obd->obd_connected_clients) -
1019 atomic_read(&obd->obd_lock_replay_clients))
1022 if (lprocfs_obd_snprintf(&page, size, &len, "evicted_clients: %d\n",
1023 obd->obd_stale_clients) <= 0)
1025 if (lprocfs_obd_snprintf(&page, size, &len, "replayed_requests: %d\n",
1026 obd->obd_replayed_requests) <= 0)
1028 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
1029 obd->obd_requests_queued_for_recovery) <= 0)
1032 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
1033 obd->obd_next_recovery_transno) <= 0)
1039 return min(count, len - (int)off);
1041 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
1043 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
1044 int count, int *eof, void *data)
1046 struct obd_device *obd = (struct obd_device *)data;
1047 LASSERT(obd != NULL);
1049 return snprintf(page, count, "%d\n",
1050 obd->obd_recovery_ir_factor);
1052 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
1054 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
1055 unsigned long count, void *data)
1057 struct obd_device *obd = (struct obd_device *)data;
1059 LASSERT(obd != NULL);
1061 rc = lprocfs_write_helper(buffer, count, &val);
1065 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
1068 obd->obd_recovery_ir_factor = val;
1071 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
1073 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
1074 int count, int *eof, void *data)
1076 struct obd_device *obd = (struct obd_device *)data;
1077 LASSERT(obd != NULL);
1079 return snprintf(page, count, "%d\n",
1080 obd->obd_recovery_timeout);
1082 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
1084 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
1085 unsigned long count, void *data)
1087 struct obd_device *obd = (struct obd_device *)data;
1089 LASSERT(obd != NULL);
1091 rc = lprocfs_write_helper(buffer, count, &val);
1095 obd->obd_recovery_timeout = val;
1098 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
1100 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
1101 int count, int *eof, void *data)
1103 struct obd_device *obd = data;
1104 LASSERT(obd != NULL);
1106 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
1108 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
1110 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
1111 unsigned long count, void *data)
1113 struct obd_device *obd = data;
1115 LASSERT(obd != NULL);
1117 rc = lprocfs_write_helper(buffer, count, &val);
1121 obd->obd_recovery_time_hard = val;
1124 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
1126 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
1127 int count, int *eof, void *data)
1129 struct obd_device *obd = (struct obd_device *)data;
1130 struct obd_device_target *target = &obd->u.obt;
1132 LASSERT(obd != NULL);
1133 LASSERT(target->obt_magic == OBT_MAGIC);
1135 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
1137 EXPORT_SYMBOL(lprocfs_target_rd_instance);
1138 #endif /* HAVE_ONLY_PROCFS_SEQ */