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 + -
显示快捷键?