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 <obd_class.h>
39 #include <lprocfs_status.h>
40 #include <lustre/lustre_idl.h>
44 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
46 struct obd_device *obd = PDE_DATA(f->f_dentry->d_inode);
48 atomic_inc(&obd->obd_evict_inprogress);
52 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
54 struct obd_device *obd = PDE_DATA(f->f_dentry->d_inode);
56 atomic_dec(&obd->obd_evict_inprogress);
57 wake_up(&obd->obd_evict_inprogress_waitq);
62 #define BUFLEN (UUID_MAX + 5)
65 lprocfs_evict_client_seq_write(struct file *file, const char *buffer,
66 size_t count, loff_t *off)
68 struct seq_file *m = file->private_data;
69 struct obd_device *obd = m->private;
72 OBD_ALLOC(kbuf, BUFLEN);
77 * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1
78 * bytes into kbuf, to ensure that the string is NUL-terminated.
79 * UUID_MAX should include a trailing NUL already.
81 if (copy_from_user(kbuf, buffer,
82 min_t(unsigned long, BUFLEN - 1, count))) {
86 tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count));
87 class_incref(obd, __func__, current);
89 if (strncmp(tmpbuf, "nid:", 4) == 0)
90 obd_export_evict_by_nid(obd, tmpbuf + 4);
91 else if (strncmp(tmpbuf, "uuid:", 5) == 0)
92 obd_export_evict_by_uuid(obd, tmpbuf + 5);
94 obd_export_evict_by_uuid(obd, tmpbuf);
96 class_decref(obd, __func__, current);
99 OBD_FREE(kbuf, BUFLEN);
102 EXPORT_SYMBOL(lprocfs_evict_client_seq_write);
104 #ifndef HAVE_ONLY_PROCFS_SEQ
105 int lprocfs_wr_evict_client(struct file *file, const char __user *buffer,
106 unsigned long count, void *data)
108 struct obd_device *obd = data;
112 OBD_ALLOC(kbuf, BUFLEN);
117 * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1
118 * bytes into kbuf, to ensure that the string is NUL-terminated.
119 * UUID_MAX should include a trailing NUL already.
121 if (copy_from_user(kbuf, buffer,
122 min_t(unsigned long, BUFLEN - 1, count))) {
126 tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count));
127 class_incref(obd, __func__, current);
129 if (strncmp(tmpbuf, "nid:", 4) == 0)
130 obd_export_evict_by_nid(obd, tmpbuf + 4);
131 else if (strncmp(tmpbuf, "uuid:", 5) == 0)
132 obd_export_evict_by_uuid(obd, tmpbuf + 5);
134 obd_export_evict_by_uuid(obd, tmpbuf);
136 class_decref(obd, __func__, current);
138 OBD_FREE(kbuf, BUFLEN);
141 EXPORT_SYMBOL(lprocfs_wr_evict_client);
143 const struct file_operations lprocfs_evict_client_fops = {
144 .owner = THIS_MODULE,
145 .read = lprocfs_fops_read,
146 .write = lprocfs_fops_write,
147 .open = lprocfs_evict_client_open,
148 .release = lprocfs_evict_client_release,
150 EXPORT_SYMBOL(lprocfs_evict_client_fops);
152 /* Function that emulates snprintf but also has the side effect of advancing
153 the page pointer for the next write into the buffer, incrementing the total
154 length written to the buffer, and decrementing the size left in the
156 static int lprocfs_obd_snprintf(char **page, int end, int *len,
157 const char *format, ...)
165 va_start(list, format);
166 n = vsnprintf(*page, end - *len, format, list);
169 *page += n; *len += n;
172 #endif /* HAVE_ONLY_PROCFS_SEQ */
176 int lprocfs_num_exports_seq_show(struct seq_file *m, void *data)
178 struct obd_device *obd = data;
180 LASSERT(obd != NULL);
181 return seq_printf(m, "%u\n", obd->obd_num_exports);
183 EXPORT_SYMBOL(lprocfs_num_exports_seq_show);
185 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
187 CDEBUG(D_CONFIG, "stat %p - data %p/%p\n", client_stat,
188 client_stat->nid_proc, client_stat->nid_stats);
190 LASSERTF(atomic_read(&client_stat->nid_exp_ref_count) == 0,
191 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
192 atomic_read(&client_stat->nid_exp_ref_count));
194 if (client_stat->nid_proc)
195 lprocfs_remove(&client_stat->nid_proc);
197 if (client_stat->nid_stats)
198 lprocfs_free_stats(&client_stat->nid_stats);
200 if (client_stat->nid_ldlm_stats)
201 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
203 OBD_FREE_PTR(client_stat);
207 void lprocfs_free_per_client_stats(struct obd_device *obd)
209 cfs_hash_t *hash = obd->obd_nid_stats_hash;
210 struct nid_stat *stat;
213 /* we need extra list - because hash_exit called to early */
214 /* not need locking because all clients is died */
215 while (!list_empty(&obd->obd_nid_stats)) {
216 stat = list_entry(obd->obd_nid_stats.next,
217 struct nid_stat, nid_list);
218 list_del_init(&stat->nid_list);
219 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
220 lprocfs_free_client_stats(stat);
224 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
226 int lprocfs_exp_nid_seq_show(struct seq_file *m, void *data)
228 struct obd_export *exp = m->private;
229 LASSERT(exp != NULL);
230 return seq_printf(m, "%s\n", obd_export_nid2str(exp));
233 int lprocfs_exp_print_uuid_seq(cfs_hash_t *hs, cfs_hash_bd_t *bd,
234 struct hlist_node *hnode, void *cb_data)
237 struct obd_export *exp = cfs_hash_object(hs, hnode);
238 struct seq_file *m = cb_data;
240 if (exp->exp_nid_stats)
241 seq_printf(m, "%s\n", obd_uuid2str(&exp->exp_client_uuid));
245 int lprocfs_exp_uuid_seq_show(struct seq_file *m, void *data)
247 struct nid_stat *stats = m->private;
248 struct obd_device *obd = stats->nid_obd;
250 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
251 lprocfs_exp_print_uuid_seq, m);
254 LPROC_SEQ_FOPS_RO(lprocfs_exp_uuid);
256 int lprocfs_exp_print_hash_seq(cfs_hash_t *hs, cfs_hash_bd_t *bd,
257 struct hlist_node *hnode, void *cb_data)
260 struct seq_file *m = cb_data;
261 struct obd_export *exp = cfs_hash_object(hs, hnode);
263 if (exp->exp_lock_hash != NULL) {
264 cfs_hash_debug_header_seq(m);
265 cfs_hash_debug_str_seq(hs, m);
270 int lprocfs_exp_hash_seq_show(struct seq_file *m, void *data)
272 struct nid_stat *stats = m->private;
273 struct obd_device *obd = stats->nid_obd;
275 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
276 lprocfs_exp_print_hash_seq, m);
279 LPROC_SEQ_FOPS_RO(lprocfs_exp_hash);
281 int lprocfs_nid_stats_clear_seq_show(struct seq_file *m, void *data)
283 return seq_printf(m, "%s\n", "Write into this file to clear all nid "
284 "stats and stale nid entries");
286 EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_show);
288 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
290 struct nid_stat *stat = obj;
293 CDEBUG(D_INFO, "refcnt %d\n", atomic_read(&stat->nid_exp_ref_count));
294 if (atomic_read(&stat->nid_exp_ref_count) == 1) {
295 /* object has only hash references. */
296 spin_lock(&stat->nid_obd->obd_nid_lock);
297 list_move(&stat->nid_list, data);
298 spin_unlock(&stat->nid_obd->obd_nid_lock);
301 /* we has reference to object - only clear data*/
303 lprocfs_clear_stats(stat->nid_stats);
309 lprocfs_nid_stats_clear_seq_write(struct file *file, const char *buffer,
310 size_t count, loff_t *off)
312 struct seq_file *m = file->private_data;
313 struct obd_device *obd = m->private;
314 struct nid_stat *client_stat;
315 struct list_head free_list;
317 INIT_LIST_HEAD(&free_list);
318 cfs_hash_cond_del(obd->obd_nid_stats_hash,
319 lprocfs_nid_stats_clear_write_cb, &free_list);
321 while (!list_empty(&free_list)) {
322 client_stat = list_entry(free_list.next, struct nid_stat,
324 list_del_init(&client_stat->nid_list);
325 lprocfs_free_client_stats(client_stat);
329 EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_write);
331 #ifndef HAVE_ONLY_PROCFS_SEQ
332 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
333 int *eof, void *data)
335 struct obd_device *obd = data;
337 LASSERT(obd != NULL);
339 return snprintf(page, count, "%u\n", obd->obd_num_exports);
341 EXPORT_SYMBOL(lprocfs_rd_num_exports);
343 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
344 int *eof, void *data)
346 struct obd_export *exp = data;
347 LASSERT(exp != NULL);
349 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
352 struct exp_uuid_cb_data {
360 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
361 int count, int *eof, int *len)
363 cb_data->page = page;
364 cb_data->count = count;
369 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
370 struct hlist_node *hnode, void *cb_data)
373 struct obd_export *exp = cfs_hash_object(hs, hnode);
374 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
376 if (exp->exp_nid_stats)
377 *data->len += snprintf((data->page + *data->len),
379 obd_uuid2str(&exp->exp_client_uuid));
383 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
384 int *eof, void *data)
386 struct nid_stat *stats = (struct nid_stat *)data;
387 struct exp_uuid_cb_data cb_data;
388 struct obd_device *obd = stats->nid_obd;
393 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
394 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
395 lprocfs_exp_print_uuid, &cb_data);
399 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
400 struct hlist_node *hnode, void *cb_data)
403 struct exp_uuid_cb_data *data = cb_data;
404 struct obd_export *exp = cfs_hash_object(hs, hnode);
406 if (exp->exp_lock_hash != NULL) {
408 *data->len += cfs_hash_debug_header(data->page,
411 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
417 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
418 int *eof, void *data)
420 struct nid_stat *stats = (struct nid_stat *)data;
421 struct exp_uuid_cb_data cb_data;
422 struct obd_device *obd = stats->nid_obd;
427 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
429 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
430 lprocfs_exp_print_hash, &cb_data);
434 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
435 int count, int *eof, void *data)
438 return snprintf(page, count, "%s\n",
439 "Write into this file to clear all nid stats and "
440 "stale nid entries");
442 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
444 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
445 unsigned long count, void *data)
447 struct obd_device *obd = (struct obd_device *)data;
448 struct nid_stat *client_stat;
449 struct list_head free_list;
451 INIT_LIST_HEAD(&free_list);
452 cfs_hash_cond_del(obd->obd_nid_stats_hash,
453 lprocfs_nid_stats_clear_write_cb, &free_list);
455 while (!list_empty(&free_list)) {
456 client_stat = list_entry(free_list.next, struct nid_stat,
458 list_del_init(&client_stat->nid_list);
459 lprocfs_free_client_stats(client_stat);
464 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
467 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
469 struct nid_stat *new_stat, *old_stat;
470 struct obd_device *obd = NULL;
471 struct proc_dir_entry *entry;
478 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
479 !exp->exp_obd->obd_nid_stats_hash)
482 /* not test against zero because eric say:
483 * You may only test nid against another nid, or LNET_NID_ANY.
484 * Anything else is nonsense.*/
485 if (!nid || *nid == LNET_NID_ANY)
488 spin_lock(&exp->exp_lock);
489 if (exp->exp_nid_stats != NULL) {
490 spin_unlock(&exp->exp_lock);
493 spin_unlock(&exp->exp_lock);
497 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
499 OBD_ALLOC_PTR(new_stat);
500 if (new_stat == NULL)
503 new_stat->nid = *nid;
504 new_stat->nid_obd = exp->exp_obd;
505 /* we need set default refcount to 1 to balance obd_disconnect */
506 atomic_set(&new_stat->nid_exp_ref_count, 1);
508 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
509 nid, &new_stat->nid_hash);
510 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
511 old_stat, libcfs_nid2str(*nid),
512 atomic_read(&new_stat->nid_exp_ref_count));
514 /* Return -EALREADY here so that we know that the /proc
515 * entry already has been created */
516 if (old_stat != new_stat) {
517 spin_lock(&exp->exp_lock);
518 if (exp->exp_nid_stats) {
519 LASSERT(exp->exp_nid_stats == old_stat);
520 nidstat_putref(exp->exp_nid_stats);
522 exp->exp_nid_stats = old_stat;
523 spin_unlock(&exp->exp_lock);
524 GOTO(destroy_new, rc = -EALREADY);
526 /* not found - create */
527 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
529 GOTO(destroy_new, rc = -ENOMEM);
531 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
532 #ifndef HAVE_ONLY_PROCFS_SEQ
533 new_stat->nid_proc = lprocfs_register(buffer,
534 obd->obd_proc_exports_entry,
537 new_stat->nid_proc = lprocfs_seq_register(buffer,
538 obd->obd_proc_exports_entry,
541 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
543 if (IS_ERR(new_stat->nid_proc)) {
544 rc = PTR_ERR(new_stat->nid_proc);
545 new_stat->nid_proc = NULL;
546 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
547 obd->obd_name, libcfs_nid2str(*nid), rc);
548 GOTO(destroy_new_ns, rc);
551 #ifndef HAVE_ONLY_PROCFS_SEQ
552 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
553 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
555 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid", new_stat,
556 &lprocfs_exp_uuid_fops);
559 CWARN("Error adding the NID stats file\n");
561 GOTO(destroy_new_ns, rc);
564 #ifndef HAVE_ONLY_PROCFS_SEQ
565 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
566 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
568 entry = lprocfs_add_simple(new_stat->nid_proc, "hash", new_stat,
569 &lprocfs_exp_hash_fops);
572 CWARN("Error adding the hash file\n");
574 GOTO(destroy_new_ns, rc);
577 spin_lock(&exp->exp_lock);
578 exp->exp_nid_stats = new_stat;
579 spin_unlock(&exp->exp_lock);
581 /* protect competitive add to list, not need locking on destroy */
582 spin_lock(&obd->obd_nid_lock);
583 list_add(&new_stat->nid_list, &obd->obd_nid_stats);
584 spin_unlock(&obd->obd_nid_lock);
589 if (new_stat->nid_proc != NULL)
590 lprocfs_remove(&new_stat->nid_proc);
591 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
594 nidstat_putref(new_stat);
595 OBD_FREE_PTR(new_stat);
598 EXPORT_SYMBOL(lprocfs_exp_setup);
600 int lprocfs_exp_cleanup(struct obd_export *exp)
602 struct nid_stat *stat = exp->exp_nid_stats;
604 if (!stat || !exp->exp_obd)
607 nidstat_putref(exp->exp_nid_stats);
608 exp->exp_nid_stats = NULL;
612 EXPORT_SYMBOL(lprocfs_exp_cleanup);
614 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
616 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
617 LASSERT(coffset < stats->ls_num); \
618 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
621 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
623 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
624 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
625 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
626 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
627 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
628 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
629 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
630 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
631 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
632 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
633 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
634 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
635 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
636 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
637 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
638 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
639 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
640 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
641 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
642 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
643 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
644 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
645 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
646 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
647 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
648 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
649 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
650 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
651 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
652 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
653 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
654 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
655 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
656 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
657 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
658 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
659 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
660 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
661 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
662 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
663 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
664 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
665 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
666 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
667 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
668 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
669 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
671 CLASSERT(NUM_OBD_STATS == OBD_COUNTER_OFFSET(putref) + 1);
673 EXPORT_SYMBOL(lprocfs_init_ops_stats);
675 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
677 struct lprocfs_stats *stats;
678 unsigned int num_stats;
681 LASSERT(obd->obd_stats == NULL);
682 LASSERT(obd->obd_proc_entry != NULL);
683 LASSERT(obd->obd_cntr_base == 0);
685 num_stats = NUM_OBD_STATS + num_private_stats;
686 stats = lprocfs_alloc_stats(num_stats, 0);
690 lprocfs_init_ops_stats(num_private_stats, stats);
692 for (i = num_private_stats; i < num_stats; i++) {
693 /* If this LBUGs, it is likely that an obd
694 * operation was added to struct obd_ops in
695 * <obd.h>, and that the corresponding line item
696 * LPROCFS_OBD_OP_INIT(.., .., opname)
697 * is missing from the list above. */
698 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
699 "Missing obd_stat initializer obd_op "
700 "operation at offset %d.\n", i - num_private_stats);
702 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
704 lprocfs_free_stats(&stats);
706 obd->obd_stats = stats;
707 obd->obd_cntr_base = num_private_stats;
711 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
713 void lprocfs_free_obd_stats(struct obd_device *obd)
716 lprocfs_free_stats(&obd->obd_stats);
718 EXPORT_SYMBOL(lprocfs_free_obd_stats);
720 int lprocfs_hash_seq_show(struct seq_file *m, void *data)
722 struct obd_device *obd = m->private;
728 c += cfs_hash_debug_header_seq(m);
729 c += cfs_hash_debug_str_seq(obd->obd_uuid_hash, m);
730 c += cfs_hash_debug_str_seq(obd->obd_nid_hash, m);
731 c += cfs_hash_debug_str_seq(obd->obd_nid_stats_hash, m);
734 EXPORT_SYMBOL(lprocfs_hash_seq_show);
736 int lprocfs_recovery_status_seq_show(struct seq_file *m, void *data)
738 struct obd_device *obd = m->private;
740 LASSERT(obd != NULL);
742 seq_printf(m, "status: ");
743 if (obd->obd_max_recoverable_clients == 0) {
744 seq_printf(m, "INACTIVE\n");
748 /* sampled unlocked, but really... */
749 if (obd->obd_recovering == 0) {
750 seq_printf(m, "COMPLETE\n");
751 seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start);
752 seq_printf(m, "recovery_duration: %lu\n",
753 obd->obd_recovery_end - obd->obd_recovery_start);
754 /* Number of clients that have completed recovery */
755 seq_printf(m, "completed_clients: %d/%d\n",
756 obd->obd_max_recoverable_clients -
757 obd->obd_stale_clients,
758 obd->obd_max_recoverable_clients);
759 seq_printf(m, "replayed_requests: %d\n",
760 obd->obd_replayed_requests);
761 seq_printf(m, "last_transno: "LPD64"\n",
762 obd->obd_next_recovery_transno - 1);
763 seq_printf(m, "VBR: %s\n", obd->obd_version_recov ?
764 "ENABLED" : "DISABLED");
765 seq_printf(m, "IR: %s\n", obd->obd_no_ir ?
766 "DISABLED" : "ENABLED");
770 seq_printf(m, "RECOVERING\n");
771 seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start);
772 seq_printf(m, "time_remaining: %lu\n",
773 cfs_time_current_sec() >=
774 obd->obd_recovery_start +
775 obd->obd_recovery_timeout ? 0 :
776 obd->obd_recovery_start +
777 obd->obd_recovery_timeout -
778 cfs_time_current_sec());
779 seq_printf(m, "connected_clients: %d/%d\n",
780 atomic_read(&obd->obd_connected_clients),
781 obd->obd_max_recoverable_clients);
782 /* Number of clients that have completed recovery */
783 seq_printf(m, "req_replay_clients: %d\n",
784 atomic_read(&obd->obd_req_replay_clients));
785 seq_printf(m, "lock_repay_clients: %d\n",
786 atomic_read(&obd->obd_lock_replay_clients));
787 seq_printf(m, "completed_clients: %d\n",
788 atomic_read(&obd->obd_connected_clients) -
789 atomic_read(&obd->obd_lock_replay_clients));
790 seq_printf(m, "evicted_clients: %d\n", obd->obd_stale_clients);
791 seq_printf(m, "replayed_requests: %d\n", obd->obd_replayed_requests);
792 seq_printf(m, "queued_requests: %d\n",
793 obd->obd_requests_queued_for_recovery);
794 seq_printf(m, "next_transno: "LPD64"\n",
795 obd->obd_next_recovery_transno);
799 EXPORT_SYMBOL(lprocfs_recovery_status_seq_show);
801 int lprocfs_ir_factor_seq_show(struct seq_file *m, void *data)
803 struct obd_device *obd = m->private;
805 LASSERT(obd != NULL);
806 return seq_printf(m, "%d\n", obd->obd_recovery_ir_factor);
808 EXPORT_SYMBOL(lprocfs_ir_factor_seq_show);
811 lprocfs_ir_factor_seq_write(struct file *file, const char *buffer,
812 size_t count, loff_t *off)
814 struct seq_file *m = file->private_data;
815 struct obd_device *obd = m->private;
818 LASSERT(obd != NULL);
819 rc = lprocfs_write_helper(buffer, count, &val);
823 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
826 obd->obd_recovery_ir_factor = val;
829 EXPORT_SYMBOL(lprocfs_ir_factor_seq_write);
831 int lprocfs_recovery_time_soft_seq_show(struct seq_file *m, void *data)
833 struct obd_device *obd = m->private;
835 LASSERT(obd != NULL);
836 return seq_printf(m, "%d\n", obd->obd_recovery_timeout);
838 EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_show);
841 lprocfs_recovery_time_soft_seq_write(struct file *file, const char *buffer,
842 size_t count, loff_t *off)
844 struct seq_file *m = file->private_data;
845 struct obd_device *obd = m->private;
848 LASSERT(obd != NULL);
849 rc = lprocfs_write_helper(buffer, count, &val);
853 obd->obd_recovery_timeout = val;
856 EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_write);
858 int lprocfs_recovery_time_hard_seq_show(struct seq_file *m, void *data)
860 struct obd_device *obd = m->private;
862 LASSERT(obd != NULL);
863 return seq_printf(m, "%u\n", obd->obd_recovery_time_hard);
865 EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_show);
868 lprocfs_recovery_time_hard_seq_write(struct file *file, const char *buffer,
869 size_t count, loff_t *off)
871 struct seq_file *m = file->private_data;
872 struct obd_device *obd = m->private;
875 LASSERT(obd != NULL);
876 rc = lprocfs_write_helper(buffer, count, &val);
880 obd->obd_recovery_time_hard = val;
883 EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_write);
885 int lprocfs_target_instance_seq_show(struct seq_file *m, void *data)
887 struct obd_device *obd = m->private;
888 struct obd_device_target *target = &obd->u.obt;
890 LASSERT(obd != NULL);
891 LASSERT(target->obt_magic == OBT_MAGIC);
892 return seq_printf(m, "%u\n", obd->u.obt.obt_instance);
894 EXPORT_SYMBOL(lprocfs_target_instance_seq_show);
896 #ifndef HAVE_ONLY_PROCFS_SEQ
897 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
898 int count, int *eof, void *data)
900 struct obd_device *obd = data;
906 c += cfs_hash_debug_header(page, count);
907 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
908 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
909 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
913 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
915 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
916 int count, int *eof, void *data)
918 struct obd_device *obd = data;
921 LASSERT(obd != NULL);
924 /* Set start of user data returned to
925 page + off since the user may have
926 requested to read much smaller than
927 what we need to read */
931 * We know we are allocated a page here.
932 * Also we know that this function will
933 * not need to write more than a page
934 * so we can truncate at PAGE_CACHE_SIZE.
936 size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
938 /* Initialize the page */
939 memset(page, 0, size);
941 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
943 if (obd->obd_max_recoverable_clients == 0) {
944 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
950 /* sampled unlocked, but really... */
951 if (obd->obd_recovering == 0) {
952 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
954 if (lprocfs_obd_snprintf(&page, size, &len,
955 "recovery_start: %lu\n",
956 obd->obd_recovery_start) <= 0)
958 if (lprocfs_obd_snprintf(&page, size, &len,
959 "recovery_duration: %lu\n",
960 obd->obd_recovery_end -
961 obd->obd_recovery_start) <= 0)
963 /* Number of clients that have completed recovery */
964 if (lprocfs_obd_snprintf(&page, size, &len,
965 "completed_clients: %d/%d\n",
966 obd->obd_max_recoverable_clients -
967 obd->obd_stale_clients,
968 obd->obd_max_recoverable_clients) <= 0)
970 if (lprocfs_obd_snprintf(&page, size, &len,
971 "replayed_requests: %d\n",
972 obd->obd_replayed_requests) <= 0)
974 if (lprocfs_obd_snprintf(&page, size, &len,
975 "last_transno: "LPD64"\n",
976 obd->obd_next_recovery_transno - 1) <= 0)
978 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
979 obd->obd_version_recov ?
980 "ENABLED" : "DISABLED") <= 0)
982 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
984 "DISABLED" : "ENABLED") <= 0)
989 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
991 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
992 obd->obd_recovery_start) <= 0)
994 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
995 cfs_time_current_sec() >=
996 obd->obd_recovery_start +
997 obd->obd_recovery_timeout ? 0 :
998 obd->obd_recovery_start +
999 obd->obd_recovery_timeout -
1000 cfs_time_current_sec()) <= 0)
1002 if (lprocfs_obd_snprintf(&page, size, &len,
1003 "connected_clients: %d/%d\n",
1004 atomic_read(&obd->obd_connected_clients),
1005 obd->obd_max_recoverable_clients) <= 0)
1007 /* Number of clients that have completed recovery */
1008 if (lprocfs_obd_snprintf(&page, size, &len, "req_replay_clients: %d\n",
1009 atomic_read(&obd->obd_req_replay_clients))
1012 if (lprocfs_obd_snprintf(&page, size, &len, "lock_repay_clients: %d\n",
1013 atomic_read(&obd->obd_lock_replay_clients))
1016 if (lprocfs_obd_snprintf(&page, size, &len, "completed_clients: %d\n",
1017 atomic_read(&obd->obd_connected_clients) -
1018 atomic_read(&obd->obd_lock_replay_clients))
1021 if (lprocfs_obd_snprintf(&page, size, &len, "evicted_clients: %d\n",
1022 obd->obd_stale_clients) <= 0)
1024 if (lprocfs_obd_snprintf(&page, size, &len, "replayed_requests: %d\n",
1025 obd->obd_replayed_requests) <= 0)
1027 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
1028 obd->obd_requests_queued_for_recovery) <= 0)
1031 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
1032 obd->obd_next_recovery_transno) <= 0)
1038 return min(count, len - (int)off);
1040 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
1042 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
1043 int count, int *eof, void *data)
1045 struct obd_device *obd = (struct obd_device *)data;
1046 LASSERT(obd != NULL);
1048 return snprintf(page, count, "%d\n",
1049 obd->obd_recovery_ir_factor);
1051 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
1053 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
1054 unsigned long count, void *data)
1056 struct obd_device *obd = (struct obd_device *)data;
1058 LASSERT(obd != NULL);
1060 rc = lprocfs_write_helper(buffer, count, &val);
1064 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
1067 obd->obd_recovery_ir_factor = val;
1070 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
1072 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
1073 int count, int *eof, void *data)
1075 struct obd_device *obd = (struct obd_device *)data;
1076 LASSERT(obd != NULL);
1078 return snprintf(page, count, "%d\n",
1079 obd->obd_recovery_timeout);
1081 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
1083 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
1084 unsigned long count, void *data)
1086 struct obd_device *obd = (struct obd_device *)data;
1088 LASSERT(obd != NULL);
1090 rc = lprocfs_write_helper(buffer, count, &val);
1094 obd->obd_recovery_timeout = val;
1097 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
1099 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
1100 int count, int *eof, void *data)
1102 struct obd_device *obd = data;
1103 LASSERT(obd != NULL);
1105 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
1107 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
1109 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
1110 unsigned long count, void *data)
1112 struct obd_device *obd = data;
1114 LASSERT(obd != NULL);
1116 rc = lprocfs_write_helper(buffer, count, &val);
1120 obd->obd_recovery_time_hard = val;
1123 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
1125 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
1126 int count, int *eof, void *data)
1128 struct obd_device *obd = (struct obd_device *)data;
1129 struct obd_device_target *target = &obd->u.obt;
1131 LASSERT(obd != NULL);
1132 LASSERT(target->obt_magic == OBT_MAGIC);
1134 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
1136 EXPORT_SYMBOL(lprocfs_target_rd_instance);
1137 #endif /* HAVE_ONLY_PROCFS_SEQ */