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 seq_file *m = file->private_data;
316 struct obd_device *obd = m->private;
317 struct nid_stat *client_stat;
318 struct list_head free_list;
320 INIT_LIST_HEAD(&free_list);
321 cfs_hash_cond_del(obd->obd_nid_stats_hash,
322 lprocfs_nid_stats_clear_write_cb, &free_list);
324 while (!list_empty(&free_list)) {
325 client_stat = list_entry(free_list.next, struct nid_stat,
327 list_del_init(&client_stat->nid_list);
328 lprocfs_free_client_stats(client_stat);
332 EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_write);
334 #ifndef HAVE_ONLY_PROCFS_SEQ
335 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
336 int *eof, void *data)
338 struct obd_device *obd = data;
340 LASSERT(obd != NULL);
342 return snprintf(page, count, "%u\n", obd->obd_num_exports);
344 EXPORT_SYMBOL(lprocfs_rd_num_exports);
346 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
347 int *eof, void *data)
349 struct obd_export *exp = data;
350 LASSERT(exp != NULL);
352 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
355 struct exp_uuid_cb_data {
363 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
364 int count, int *eof, int *len)
366 cb_data->page = page;
367 cb_data->count = count;
372 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
373 struct hlist_node *hnode, void *cb_data)
376 struct obd_export *exp = cfs_hash_object(hs, hnode);
377 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
379 if (exp->exp_nid_stats)
380 *data->len += snprintf((data->page + *data->len),
382 obd_uuid2str(&exp->exp_client_uuid));
386 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
387 int *eof, void *data)
389 struct nid_stat *stats = (struct nid_stat *)data;
390 struct exp_uuid_cb_data cb_data;
391 struct obd_device *obd = stats->nid_obd;
396 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
397 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
398 lprocfs_exp_print_uuid, &cb_data);
402 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
403 struct hlist_node *hnode, void *cb_data)
406 struct exp_uuid_cb_data *data = cb_data;
407 struct obd_export *exp = cfs_hash_object(hs, hnode);
409 if (exp->exp_lock_hash != NULL) {
411 *data->len += cfs_hash_debug_header(data->page,
414 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
420 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
421 int *eof, void *data)
423 struct nid_stat *stats = (struct nid_stat *)data;
424 struct exp_uuid_cb_data cb_data;
425 struct obd_device *obd = stats->nid_obd;
430 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
432 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
433 lprocfs_exp_print_hash, &cb_data);
437 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
438 int count, int *eof, void *data)
441 return snprintf(page, count, "%s\n",
442 "Write into this file to clear all nid stats and "
443 "stale nid entries");
445 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
447 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
448 unsigned long count, void *data)
450 struct obd_device *obd = (struct obd_device *)data;
451 struct nid_stat *client_stat;
452 struct list_head free_list;
454 INIT_LIST_HEAD(&free_list);
455 cfs_hash_cond_del(obd->obd_nid_stats_hash,
456 lprocfs_nid_stats_clear_write_cb, &free_list);
458 while (!list_empty(&free_list)) {
459 client_stat = list_entry(free_list.next, struct nid_stat,
461 list_del_init(&client_stat->nid_list);
462 lprocfs_free_client_stats(client_stat);
467 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
470 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
472 struct nid_stat *new_stat, *old_stat;
473 struct obd_device *obd = NULL;
474 struct proc_dir_entry *entry;
481 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
482 !exp->exp_obd->obd_nid_stats_hash)
485 /* not test against zero because eric say:
486 * You may only test nid against another nid, or LNET_NID_ANY.
487 * Anything else is nonsense.*/
488 if (!nid || *nid == LNET_NID_ANY)
491 spin_lock(&exp->exp_lock);
492 if (exp->exp_nid_stats != NULL) {
493 spin_unlock(&exp->exp_lock);
496 spin_unlock(&exp->exp_lock);
500 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
502 OBD_ALLOC_PTR(new_stat);
503 if (new_stat == NULL)
506 new_stat->nid = *nid;
507 new_stat->nid_obd = exp->exp_obd;
508 /* we need set default refcount to 1 to balance obd_disconnect */
509 atomic_set(&new_stat->nid_exp_ref_count, 1);
511 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
512 nid, &new_stat->nid_hash);
513 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
514 old_stat, libcfs_nid2str(*nid),
515 atomic_read(&new_stat->nid_exp_ref_count));
517 /* Return -EALREADY here so that we know that the /proc
518 * entry already has been created */
519 if (old_stat != new_stat) {
520 spin_lock(&exp->exp_lock);
521 if (exp->exp_nid_stats) {
522 LASSERT(exp->exp_nid_stats == old_stat);
523 nidstat_putref(exp->exp_nid_stats);
525 exp->exp_nid_stats = old_stat;
526 spin_unlock(&exp->exp_lock);
527 GOTO(destroy_new, rc = -EALREADY);
529 /* not found - create */
530 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
532 GOTO(destroy_new, rc = -ENOMEM);
534 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
535 #ifndef HAVE_ONLY_PROCFS_SEQ
536 new_stat->nid_proc = lprocfs_register(buffer,
537 obd->obd_proc_exports_entry,
540 new_stat->nid_proc = lprocfs_seq_register(buffer,
541 obd->obd_proc_exports_entry,
544 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
546 if (IS_ERR(new_stat->nid_proc)) {
547 rc = PTR_ERR(new_stat->nid_proc);
548 new_stat->nid_proc = NULL;
549 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
550 obd->obd_name, libcfs_nid2str(*nid), rc);
551 GOTO(destroy_new_ns, rc);
554 #ifndef HAVE_ONLY_PROCFS_SEQ
555 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
556 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
558 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid", new_stat,
559 &lprocfs_exp_uuid_fops);
562 CWARN("Error adding the NID stats file\n");
564 GOTO(destroy_new_ns, rc);
567 #ifndef HAVE_ONLY_PROCFS_SEQ
568 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
569 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
571 entry = lprocfs_add_simple(new_stat->nid_proc, "hash", new_stat,
572 &lprocfs_exp_hash_fops);
575 CWARN("Error adding the hash file\n");
577 GOTO(destroy_new_ns, rc);
580 spin_lock(&exp->exp_lock);
581 exp->exp_nid_stats = new_stat;
582 spin_unlock(&exp->exp_lock);
584 /* protect competitive add to list, not need locking on destroy */
585 spin_lock(&obd->obd_nid_lock);
586 list_add(&new_stat->nid_list, &obd->obd_nid_stats);
587 spin_unlock(&obd->obd_nid_lock);
592 if (new_stat->nid_proc != NULL)
593 lprocfs_remove(&new_stat->nid_proc);
594 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
597 nidstat_putref(new_stat);
598 OBD_FREE_PTR(new_stat);
601 EXPORT_SYMBOL(lprocfs_exp_setup);
603 int lprocfs_exp_cleanup(struct obd_export *exp)
605 struct nid_stat *stat = exp->exp_nid_stats;
607 if (!stat || !exp->exp_obd)
610 nidstat_putref(exp->exp_nid_stats);
611 exp->exp_nid_stats = NULL;
615 EXPORT_SYMBOL(lprocfs_exp_cleanup);
617 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
619 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
620 LASSERT(coffset < stats->ls_num); \
621 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
624 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
626 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
627 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
628 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
629 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
630 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
631 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
632 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
633 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
634 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
635 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
636 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
637 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
638 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
639 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
640 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
641 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
642 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
643 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
644 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
645 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
646 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
647 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
648 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
649 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
650 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
651 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
652 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
653 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
654 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
655 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
656 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
657 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
658 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
659 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
660 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
661 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
662 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
663 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
664 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
665 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
666 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
667 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
668 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
669 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
670 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
671 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
672 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
674 CLASSERT(NUM_OBD_STATS == OBD_COUNTER_OFFSET(putref) + 1);
676 EXPORT_SYMBOL(lprocfs_init_ops_stats);
678 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
680 struct lprocfs_stats *stats;
681 unsigned int num_stats;
684 LASSERT(obd->obd_stats == NULL);
685 LASSERT(obd->obd_proc_entry != NULL);
686 LASSERT(obd->obd_cntr_base == 0);
688 num_stats = NUM_OBD_STATS + num_private_stats;
689 stats = lprocfs_alloc_stats(num_stats, 0);
693 lprocfs_init_ops_stats(num_private_stats, stats);
695 for (i = num_private_stats; i < num_stats; i++) {
696 /* If this LBUGs, it is likely that an obd
697 * operation was added to struct obd_ops in
698 * <obd.h>, and that the corresponding line item
699 * LPROCFS_OBD_OP_INIT(.., .., opname)
700 * is missing from the list above. */
701 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
702 "Missing obd_stat initializer obd_op "
703 "operation at offset %d.\n", i - num_private_stats);
705 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
707 lprocfs_free_stats(&stats);
709 obd->obd_stats = stats;
710 obd->obd_cntr_base = num_private_stats;
714 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
716 void lprocfs_free_obd_stats(struct obd_device *obd)
719 lprocfs_free_stats(&obd->obd_stats);
721 EXPORT_SYMBOL(lprocfs_free_obd_stats);
723 int lprocfs_hash_seq_show(struct seq_file *m, void *data)
725 struct obd_device *obd = m->private;
731 c += cfs_hash_debug_header_seq(m);
732 c += cfs_hash_debug_str_seq(obd->obd_uuid_hash, m);
733 c += cfs_hash_debug_str_seq(obd->obd_nid_hash, m);
734 c += cfs_hash_debug_str_seq(obd->obd_nid_stats_hash, m);
737 EXPORT_SYMBOL(lprocfs_hash_seq_show);
739 int lprocfs_recovery_status_seq_show(struct seq_file *m, void *data)
741 struct obd_device *obd = m->private;
743 LASSERT(obd != NULL);
745 seq_printf(m, "status: ");
746 if (obd->obd_max_recoverable_clients == 0) {
747 seq_printf(m, "INACTIVE\n");
751 /* sampled unlocked, but really... */
752 if (obd->obd_recovering == 0) {
753 seq_printf(m, "COMPLETE\n");
754 seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start);
755 seq_printf(m, "recovery_duration: %lu\n",
756 obd->obd_recovery_end - obd->obd_recovery_start);
757 /* Number of clients that have completed recovery */
758 seq_printf(m, "completed_clients: %d/%d\n",
759 obd->obd_max_recoverable_clients -
760 obd->obd_stale_clients,
761 obd->obd_max_recoverable_clients);
762 seq_printf(m, "replayed_requests: %d\n",
763 obd->obd_replayed_requests);
764 seq_printf(m, "last_transno: "LPD64"\n",
765 obd->obd_next_recovery_transno - 1);
766 seq_printf(m, "VBR: %s\n", obd->obd_version_recov ?
767 "ENABLED" : "DISABLED");
768 seq_printf(m, "IR: %s\n", obd->obd_no_ir ?
769 "DISABLED" : "ENABLED");
773 seq_printf(m, "RECOVERING\n");
774 seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start);
775 seq_printf(m, "time_remaining: %lu\n",
776 cfs_time_current_sec() >=
777 obd->obd_recovery_start +
778 obd->obd_recovery_timeout ? 0 :
779 obd->obd_recovery_start +
780 obd->obd_recovery_timeout -
781 cfs_time_current_sec());
782 seq_printf(m, "connected_clients: %d/%d\n",
783 atomic_read(&obd->obd_connected_clients),
784 obd->obd_max_recoverable_clients);
785 /* Number of clients that have completed recovery */
786 seq_printf(m, "req_replay_clients: %d\n",
787 atomic_read(&obd->obd_req_replay_clients));
788 seq_printf(m, "lock_repay_clients: %d\n",
789 atomic_read(&obd->obd_lock_replay_clients));
790 seq_printf(m, "completed_clients: %d\n",
791 atomic_read(&obd->obd_connected_clients) -
792 atomic_read(&obd->obd_lock_replay_clients));
793 seq_printf(m, "evicted_clients: %d\n", obd->obd_stale_clients);
794 seq_printf(m, "replayed_requests: %d\n", obd->obd_replayed_requests);
795 seq_printf(m, "queued_requests: %d\n",
796 obd->obd_requests_queued_for_recovery);
797 seq_printf(m, "next_transno: "LPD64"\n",
798 obd->obd_next_recovery_transno);
802 EXPORT_SYMBOL(lprocfs_recovery_status_seq_show);
804 int lprocfs_ir_factor_seq_show(struct seq_file *m, void *data)
806 struct obd_device *obd = m->private;
808 LASSERT(obd != NULL);
809 return seq_printf(m, "%d\n", obd->obd_recovery_ir_factor);
811 EXPORT_SYMBOL(lprocfs_ir_factor_seq_show);
814 lprocfs_ir_factor_seq_write(struct file *file, const char *buffer,
815 size_t count, loff_t *off)
817 struct seq_file *m = file->private_data;
818 struct obd_device *obd = m->private;
821 LASSERT(obd != NULL);
822 rc = lprocfs_write_helper(buffer, count, &val);
826 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
829 obd->obd_recovery_ir_factor = val;
832 EXPORT_SYMBOL(lprocfs_ir_factor_seq_write);
834 int lprocfs_recovery_time_soft_seq_show(struct seq_file *m, void *data)
836 struct obd_device *obd = m->private;
838 LASSERT(obd != NULL);
839 return seq_printf(m, "%d\n", obd->obd_recovery_timeout);
841 EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_show);
844 lprocfs_recovery_time_soft_seq_write(struct file *file, const char *buffer,
845 size_t count, loff_t *off)
847 struct seq_file *m = file->private_data;
848 struct obd_device *obd = m->private;
851 LASSERT(obd != NULL);
852 rc = lprocfs_write_helper(buffer, count, &val);
856 obd->obd_recovery_timeout = val;
859 EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_write);
861 int lprocfs_recovery_time_hard_seq_show(struct seq_file *m, void *data)
863 struct obd_device *obd = m->private;
865 LASSERT(obd != NULL);
866 return seq_printf(m, "%u\n", obd->obd_recovery_time_hard);
868 EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_show);
871 lprocfs_recovery_time_hard_seq_write(struct file *file, const char *buffer,
872 size_t count, loff_t *off)
874 struct seq_file *m = file->private_data;
875 struct obd_device *obd = m->private;
878 LASSERT(obd != NULL);
879 rc = lprocfs_write_helper(buffer, count, &val);
883 obd->obd_recovery_time_hard = val;
886 EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_write);
888 int lprocfs_target_instance_seq_show(struct seq_file *m, void *data)
890 struct obd_device *obd = m->private;
891 struct obd_device_target *target = &obd->u.obt;
893 LASSERT(obd != NULL);
894 LASSERT(target->obt_magic == OBT_MAGIC);
895 return seq_printf(m, "%u\n", obd->u.obt.obt_instance);
897 EXPORT_SYMBOL(lprocfs_target_instance_seq_show);
899 #ifndef HAVE_ONLY_PROCFS_SEQ
900 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
901 int count, int *eof, void *data)
903 struct obd_device *obd = data;
909 c += cfs_hash_debug_header(page, count);
910 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
911 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
912 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
916 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
918 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
919 int count, int *eof, void *data)
921 struct obd_device *obd = data;
924 LASSERT(obd != NULL);
927 /* Set start of user data returned to
928 page + off since the user may have
929 requested to read much smaller than
930 what we need to read */
934 * We know we are allocated a page here.
935 * Also we know that this function will
936 * not need to write more than a page
937 * so we can truncate at PAGE_CACHE_SIZE.
939 size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
941 /* Initialize the page */
942 memset(page, 0, size);
944 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
946 if (obd->obd_max_recoverable_clients == 0) {
947 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
953 /* sampled unlocked, but really... */
954 if (obd->obd_recovering == 0) {
955 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
957 if (lprocfs_obd_snprintf(&page, size, &len,
958 "recovery_start: %lu\n",
959 obd->obd_recovery_start) <= 0)
961 if (lprocfs_obd_snprintf(&page, size, &len,
962 "recovery_duration: %lu\n",
963 obd->obd_recovery_end -
964 obd->obd_recovery_start) <= 0)
966 /* Number of clients that have completed recovery */
967 if (lprocfs_obd_snprintf(&page, size, &len,
968 "completed_clients: %d/%d\n",
969 obd->obd_max_recoverable_clients -
970 obd->obd_stale_clients,
971 obd->obd_max_recoverable_clients) <= 0)
973 if (lprocfs_obd_snprintf(&page, size, &len,
974 "replayed_requests: %d\n",
975 obd->obd_replayed_requests) <= 0)
977 if (lprocfs_obd_snprintf(&page, size, &len,
978 "last_transno: "LPD64"\n",
979 obd->obd_next_recovery_transno - 1) <= 0)
981 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
982 obd->obd_version_recov ?
983 "ENABLED" : "DISABLED") <= 0)
985 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
987 "DISABLED" : "ENABLED") <= 0)
992 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
994 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
995 obd->obd_recovery_start) <= 0)
997 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
998 cfs_time_current_sec() >=
999 obd->obd_recovery_start +
1000 obd->obd_recovery_timeout ? 0 :
1001 obd->obd_recovery_start +
1002 obd->obd_recovery_timeout -
1003 cfs_time_current_sec()) <= 0)
1005 if (lprocfs_obd_snprintf(&page, size, &len,
1006 "connected_clients: %d/%d\n",
1007 atomic_read(&obd->obd_connected_clients),
1008 obd->obd_max_recoverable_clients) <= 0)
1010 /* Number of clients that have completed recovery */
1011 if (lprocfs_obd_snprintf(&page, size, &len, "req_replay_clients: %d\n",
1012 atomic_read(&obd->obd_req_replay_clients))
1015 if (lprocfs_obd_snprintf(&page, size, &len, "lock_repay_clients: %d\n",
1016 atomic_read(&obd->obd_lock_replay_clients))
1019 if (lprocfs_obd_snprintf(&page, size, &len, "completed_clients: %d\n",
1020 atomic_read(&obd->obd_connected_clients) -
1021 atomic_read(&obd->obd_lock_replay_clients))
1024 if (lprocfs_obd_snprintf(&page, size, &len, "evicted_clients: %d\n",
1025 obd->obd_stale_clients) <= 0)
1027 if (lprocfs_obd_snprintf(&page, size, &len, "replayed_requests: %d\n",
1028 obd->obd_replayed_requests) <= 0)
1030 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
1031 obd->obd_requests_queued_for_recovery) <= 0)
1034 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
1035 obd->obd_next_recovery_transno) <= 0)
1041 return min(count, len - (int)off);
1043 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
1045 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
1046 int count, int *eof, void *data)
1048 struct obd_device *obd = (struct obd_device *)data;
1049 LASSERT(obd != NULL);
1051 return snprintf(page, count, "%d\n",
1052 obd->obd_recovery_ir_factor);
1054 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
1056 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
1057 unsigned long count, void *data)
1059 struct obd_device *obd = (struct obd_device *)data;
1061 LASSERT(obd != NULL);
1063 rc = lprocfs_write_helper(buffer, count, &val);
1067 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
1070 obd->obd_recovery_ir_factor = val;
1073 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
1075 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
1076 int count, int *eof, void *data)
1078 struct obd_device *obd = (struct obd_device *)data;
1079 LASSERT(obd != NULL);
1081 return snprintf(page, count, "%d\n",
1082 obd->obd_recovery_timeout);
1084 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
1086 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
1087 unsigned long count, void *data)
1089 struct obd_device *obd = (struct obd_device *)data;
1091 LASSERT(obd != NULL);
1093 rc = lprocfs_write_helper(buffer, count, &val);
1097 obd->obd_recovery_timeout = val;
1100 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
1102 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
1103 int count, int *eof, void *data)
1105 struct obd_device *obd = data;
1106 LASSERT(obd != NULL);
1108 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
1110 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
1112 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
1113 unsigned long count, void *data)
1115 struct obd_device *obd = data;
1117 LASSERT(obd != NULL);
1119 rc = lprocfs_write_helper(buffer, count, &val);
1123 obd->obd_recovery_time_hard = val;
1126 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
1128 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
1129 int count, int *eof, void *data)
1131 struct obd_device *obd = (struct obd_device *)data;
1132 struct obd_device_target *target = &obd->u.obt;
1134 LASSERT(obd != NULL);
1135 LASSERT(target->obt_magic == OBT_MAGIC);
1137 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
1139 EXPORT_SYMBOL(lprocfs_target_rd_instance);
1140 #endif /* HAVE_ONLY_PROCFS_SEQ */