tracefile.c
来自「lustre 1.6.5 source code」· C语言 代码 · 共 1,115 行 · 第 1/3 页
C
1,115 行
cdls->cdls_delay = libcfs_console_min_delay; else if (cdls->cdls_delay > libcfs_console_max_delay) cdls->cdls_delay = libcfs_console_max_delay; } /* ensure cdls_next is never zero after it's been seen */ cdls->cdls_next = (cfs_time_current() + cdls->cdls_delay) | 1; } if (tcd != NULL) { print_to_console(&header, mask, string_buf, needed, file, fn); trace_put_tcd(tcd); } else { string_buf = trace_get_console_buffer(); needed = 0; if (format1 != NULL) { va_copy(ap, args); needed = vsnprintf(string_buf, TRACE_CONSOLE_BUFFER_SIZE, format1, ap); va_end(ap); } if (format2 != NULL) { remain = TRACE_CONSOLE_BUFFER_SIZE - needed; if (remain > 0) { va_start(ap, format2); needed += vsnprintf(string_buf+needed, remain, format2, ap); va_end(ap); } } print_to_console(&header, mask, string_buf, needed, file, fn); trace_put_console_buffer(string_buf); } if (cdls != NULL && cdls->cdls_count != 0) { string_buf = trace_get_console_buffer(); needed = snprintf(string_buf, TRACE_CONSOLE_BUFFER_SIZE, "Skipped %d previous similar message%s\n", cdls->cdls_count, (cdls->cdls_count > 1) ? "s" : ""); print_to_console(&header, mask, string_buf, needed, file, fn); trace_put_console_buffer(string_buf); cdls->cdls_count = 0; } return 0;}EXPORT_SYMBOL(libcfs_debug_vmsg2);voidlibcfs_assertion_failed(const char *expr, const char *file, const char *func, const int line){ libcfs_debug_msg(NULL, 0, D_EMERG, file, func, line, "ASSERTION(%s) failed\n", expr); LBUG();}EXPORT_SYMBOL(libcfs_assertion_failed);voidtrace_assertion_failed(const char *str, const char *fn, const char *file, int line){ struct ptldebug_header hdr; libcfs_panic_in_progress = 1; libcfs_catastrophe = 1; mb(); set_ptldebug_header(&hdr, DEBUG_SUBSYSTEM, D_EMERG, line, CDEBUG_STACK()); print_to_console(&hdr, D_EMERG, str, strlen(str), file, fn); LIBCFS_PANIC("Lustre debug assertion failure\n"); /* not reached */}static voidpanic_collect_pages(struct page_collection *pc){ /* Do the collect_pages job on a single CPU: assumes that all other * CPUs have been stopped during a panic. If this isn't true for some * arch, this will have to be implemented separately in each arch. */ int i; int j; struct trace_cpu_data *tcd; CFS_INIT_LIST_HEAD(&pc->pc_pages); tcd_for_each(tcd, i, j) { list_splice_init(&tcd->tcd_pages, &pc->pc_pages); tcd->tcd_cur_pages = 0; if (pc->pc_want_daemon_pages) { list_splice_init(&tcd->tcd_daemon_pages, &pc->pc_pages); tcd->tcd_cur_daemon_pages = 0; } }}static void collect_pages_on_cpu(void *info){ struct trace_cpu_data *tcd; struct page_collection *pc = info; int i; spin_lock(&pc->pc_lock); tcd_for_each_type_lock(tcd, i) { list_splice_init(&tcd->tcd_pages, &pc->pc_pages); tcd->tcd_cur_pages = 0; if (pc->pc_want_daemon_pages) { list_splice_init(&tcd->tcd_daemon_pages, &pc->pc_pages); tcd->tcd_cur_daemon_pages = 0; } } spin_unlock(&pc->pc_lock);}static void collect_pages(struct page_collection *pc){ CFS_INIT_LIST_HEAD(&pc->pc_pages); if (libcfs_panic_in_progress) panic_collect_pages(pc); else trace_call_on_all_cpus(collect_pages_on_cpu, pc);}static void put_pages_back_on_cpu(void *info){ struct page_collection *pc = info; struct trace_cpu_data *tcd; struct list_head *cur_head; struct trace_page *tage; struct trace_page *tmp; int i; spin_lock(&pc->pc_lock); tcd_for_each_type_lock(tcd, i) { cur_head = tcd->tcd_pages.next; list_for_each_entry_safe(tage, tmp, &pc->pc_pages, linkage) { __LASSERT_TAGE_INVARIANT(tage); if (tage->cpu != smp_processor_id() || tage->type != i) continue; tage_to_tail(tage, cur_head); tcd->tcd_cur_pages++; } } spin_unlock(&pc->pc_lock);}static void put_pages_back(struct page_collection *pc){ if (!libcfs_panic_in_progress) trace_call_on_all_cpus(put_pages_back_on_cpu, pc);}/* Add pages to a per-cpu debug daemon ringbuffer. This buffer makes sure that * we have a good amount of data at all times for dumping during an LBUG, even * if we have been steadily writing (and otherwise discarding) pages via the * debug daemon. */static void put_pages_on_tcd_daemon_list(struct page_collection *pc, struct trace_cpu_data *tcd){ struct trace_page *tage; struct trace_page *tmp; spin_lock(&pc->pc_lock); list_for_each_entry_safe(tage, tmp, &pc->pc_pages, linkage) { __LASSERT_TAGE_INVARIANT(tage); if (tage->cpu != smp_processor_id() || tage->type != tcd->tcd_type) continue; tage_to_tail(tage, &tcd->tcd_daemon_pages); tcd->tcd_cur_daemon_pages++; if (tcd->tcd_cur_daemon_pages > tcd->tcd_max_pages) { struct trace_page *victim; __LASSERT(!list_empty(&tcd->tcd_daemon_pages)); victim = tage_from_list(tcd->tcd_daemon_pages.next); __LASSERT_TAGE_INVARIANT(victim); list_del(&victim->linkage); tage_free(victim); tcd->tcd_cur_daemon_pages--; } } spin_unlock(&pc->pc_lock);}static void put_pages_on_daemon_list_on_cpu(void *info){ struct trace_cpu_data *tcd; int i; tcd_for_each_type_lock(tcd, i) put_pages_on_tcd_daemon_list(info, tcd);}static void put_pages_on_daemon_list(struct page_collection *pc){ trace_call_on_all_cpus(put_pages_on_daemon_list_on_cpu, pc);}void trace_debug_print(void){ struct page_collection pc; struct trace_page *tage; struct trace_page *tmp; spin_lock_init(&pc.pc_lock); pc.pc_want_daemon_pages = 1; collect_pages(&pc); list_for_each_entry_safe(tage, tmp, &pc.pc_pages, linkage) { char *p, *file, *fn; cfs_page_t *page; __LASSERT_TAGE_INVARIANT(tage); page = tage->page; p = cfs_page_address(page); while (p < ((char *)cfs_page_address(page) + tage->used)) { struct ptldebug_header *hdr; int len; hdr = (void *)p; p += sizeof(*hdr); file = p; p += strlen(file) + 1; fn = p; p += strlen(fn) + 1; len = hdr->ph_len - (p - (char *)hdr); print_to_console(hdr, D_EMERG, p, len, file, fn); p += len; } list_del(&tage->linkage); tage_free(tage); }}int tracefile_dump_all_pages(char *filename){ struct page_collection pc; cfs_file_t *filp; struct trace_page *tage; struct trace_page *tmp; int rc; CFS_DECL_MMSPACE; tracefile_write_lock(); filp = cfs_filp_open(filename, O_CREAT|O_EXCL|O_WRONLY|O_LARGEFILE, 0600, &rc); if (!filp) { if (rc != -EEXIST) printk(KERN_ERR "LustreError: can't open %s for dump: rc %d\n", filename, rc); goto out; } spin_lock_init(&pc.pc_lock); pc.pc_want_daemon_pages = 1; collect_pages(&pc); if (list_empty(&pc.pc_pages)) { rc = 0; goto close; } /* ok, for now, just write the pages. in the future we'll be building * iobufs with the pages and calling generic_direct_IO */ CFS_MMSPACE_OPEN; list_for_each_entry_safe(tage, tmp, &pc.pc_pages, linkage) { __LASSERT_TAGE_INVARIANT(tage); rc = cfs_filp_write(filp, cfs_page_address(tage->page), tage->used, cfs_filp_poff(filp)); if (rc != (int)tage->used) { printk(KERN_WARNING "wanted to write %u but wrote " "%d\n", tage->used, rc); put_pages_back(&pc); __LASSERT(list_empty(&pc.pc_pages)); break; } list_del(&tage->linkage); tage_free(tage); } CFS_MMSPACE_CLOSE; rc = cfs_filp_fsync(filp); if (rc) printk(KERN_ERR "sync returns %d\n", rc); close: cfs_filp_close(filp); out: tracefile_write_unlock(); return rc;}void trace_flush_pages(void){ struct page_collection pc; struct trace_page *tage; struct trace_page *tmp; spin_lock_init(&pc.pc_lock); pc.pc_want_daemon_pages = 1; collect_pages(&pc); list_for_each_entry_safe(tage, tmp, &pc.pc_pages, linkage) { __LASSERT_TAGE_INVARIANT(tage); list_del(&tage->linkage); tage_free(tage); }}int trace_copyin_string(char *knl_buffer, int knl_buffer_nob, const char *usr_buffer, int usr_buffer_nob){ int nob; if (usr_buffer_nob > knl_buffer_nob) return -EOVERFLOW; if (copy_from_user((void *)knl_buffer, (void *)usr_buffer, usr_buffer_nob)) return -EFAULT; nob = strnlen(knl_buffer, usr_buffer_nob); while (nob-- >= 0) /* strip trailing whitespace */ if (!isspace(knl_buffer[nob])) break; if (nob < 0) /* empty string */ return -EINVAL; if (nob == knl_buffer_nob) /* no space to terminate */ return -EOVERFLOW; knl_buffer[nob + 1] = 0; /* terminate */ return 0;}int trace_copyout_string(char *usr_buffer, int usr_buffer_nob, const char *knl_buffer, char *append){ /* NB if 'append' != NULL, it's a single character to append to the * copied out string - usually "\n", for /proc entries and "" (i.e. a * terminating zero byte) for sysctl entries */ int nob = strlen(knl_buffer); if (nob > usr_buffer_nob)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?