示例#1
0
文件: tracefile.c 项目: DCteam/lustre
void
cfs_trace_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;
        cfs_mb();

        cfs_set_ptldebug_header(&hdr, DEBUG_SUBSYSTEM, D_EMERG, line,
                                CDEBUG_STACK());

        cfs_print_to_console(&hdr, D_EMERG, str, strlen(str), file, fn);

        LIBCFS_PANIC("Lustre debug assertion failure\n");

        /* not reached */
}
示例#2
0
文件: tracefile.c 项目: DCteam/lustre
int libcfs_debug_vmsg2(cfs_debug_limit_state_t *cdls, int subsys, int mask,
                       const char *file, const char *fn, const int line,
                       const char *format1, va_list args,
                       const char *format2, ...)
{
        struct cfs_trace_cpu_data *tcd = NULL;
        struct ptldebug_header     header = {0};
        struct cfs_trace_page     *tage;
        /* string_buf is used only if tcd != NULL, and is always set then */
        char                      *string_buf = NULL;
        char                      *debug_buf;
        int                        known_size;
        int                        needed = 85; /* average message length */
        int                        max_nob;
        va_list                    ap;
        int                        depth;
        int                        i;
        int                        remain;

        if (strchr(file, '/'))
                file = strrchr(file, '/') + 1;

        tcd = cfs_trace_get_tcd();

        /* cfs_trace_get_tcd() grabs a lock, which disables preemption and
         * pins us to a particular CPU.  This avoids an smp_processor_id()
         * warning on Linux when debugging is enabled. */
        cfs_set_ptldebug_header(&header, subsys, mask, line, CDEBUG_STACK());

        if (tcd == NULL)                /* arch may not log in IRQ context */
                goto console;

        if (tcd->tcd_cur_pages == 0)
                header.ph_flags |= PH_FLAG_FIRST_RECORD;

        if (tcd->tcd_shutting_down) {
                cfs_trace_put_tcd(tcd);
                tcd = NULL;
                goto console;
        }

        depth = __current_nesting_level();
        known_size = strlen(file) + 1 + depth;
        if (fn)
                known_size += strlen(fn) + 1;

        if (libcfs_debug_binary)
                known_size += sizeof(header);

        /*/
         * '2' used because vsnprintf return real size required for output
         * _without_ terminating NULL.
         * if needed is to small for this format.
         */
        for (i = 0; i < 2; i++) {
                tage = cfs_trace_get_tage(tcd, needed + known_size + 1);
                if (tage == NULL) {
                        if (needed + known_size > CFS_PAGE_SIZE)
                                mask |= D_ERROR;

                        cfs_trace_put_tcd(tcd);
                        tcd = NULL;
                        goto console;
                }

                string_buf = (char *)cfs_page_address(tage->page) +
                                        tage->used + known_size;

                max_nob = CFS_PAGE_SIZE - tage->used - known_size;
                if (max_nob <= 0) {
                        printk(CFS_KERN_EMERG "negative max_nob: %d\n",
                               max_nob);
                        mask |= D_ERROR;
                        cfs_trace_put_tcd(tcd);
                        tcd = NULL;
                        goto console;
                }

                needed = 0;
                if (format1) {
                        va_copy(ap, args);
                        needed = vsnprintf(string_buf, max_nob, format1, ap);
                        va_end(ap);
                }

                if (format2) {
                        remain = max_nob - needed;
                        if (remain < 0)
                                remain = 0;

                        va_start(ap, format2);
                        needed += vsnprintf(string_buf + needed, remain,
                                            format2, ap);
                        va_end(ap);
                }

                if (needed < max_nob) /* well. printing ok.. */
                        break;
        }

        if (*(string_buf+needed-1) != '\n')
                printk(CFS_KERN_INFO "format at %s:%d:%s doesn't end in newline\n",
                       file, line, fn);

        header.ph_len = known_size + needed;
        debug_buf = (char *)cfs_page_address(tage->page) + tage->used;

        if (libcfs_debug_binary) {
                memcpy(debug_buf, &header, sizeof(header));
                tage->used += sizeof(header);
                debug_buf += sizeof(header);
        }

        /* indent message according to the nesting level */
        while (depth-- > 0) {
                *(debug_buf++) = '.';
                ++ tage->used;
        }

        strcpy(debug_buf, file);
        tage->used += strlen(file) + 1;
        debug_buf += strlen(file) + 1;

        if (fn) {
                strcpy(debug_buf, fn);
                tage->used += strlen(fn) + 1;
                debug_buf += strlen(fn) + 1;
        }

        __LASSERT(debug_buf == string_buf);

        tage->used += needed;
        __LASSERT (tage->used <= CFS_PAGE_SIZE);

console:
        if ((mask & libcfs_printk) == 0) {
                /* no console output requested */
                if (tcd != NULL)
                        cfs_trace_put_tcd(tcd);
                return 1;
        }

        if (cdls != NULL) {
                if (libcfs_console_ratelimit &&
                    cdls->cdls_next != 0 &&     /* not first time ever */
                    !cfs_time_after(cfs_time_current(), cdls->cdls_next)) {
                        /* skipping a console message */
                        cdls->cdls_count++;
                        if (tcd != NULL)
                                cfs_trace_put_tcd(tcd);
                        return 1;
                }

                if (cfs_time_after(cfs_time_current(), cdls->cdls_next +
                                                       libcfs_console_max_delay
                                                       + cfs_time_seconds(10))) {
                        /* last timeout was a long time ago */
                        cdls->cdls_delay /= libcfs_console_backoff * 4;
                } else {
                        cdls->cdls_delay *= libcfs_console_backoff;

                        if (cdls->cdls_delay < libcfs_console_min_delay)
                                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) {
                cfs_print_to_console(&header, mask, string_buf, needed, file,
                                     fn);
                cfs_trace_put_tcd(tcd);
        } else {
                string_buf = cfs_trace_get_console_buffer();

                needed = 0;
                if (format1 != NULL) {
                        va_copy(ap, args);
                        needed = vsnprintf(string_buf,
                                           CFS_TRACE_CONSOLE_BUFFER_SIZE,
                                           format1, ap);
                        va_end(ap);
                }
                if (format2 != NULL) {
                        remain = CFS_TRACE_CONSOLE_BUFFER_SIZE - needed;
                        if (remain > 0) {
                                va_start(ap, format2);
                                needed += vsnprintf(string_buf+needed, remain, format2, ap);
                                va_end(ap);
                        }
                }
                cfs_print_to_console(&header, mask,
                                     string_buf, needed, file, fn);

                cfs_trace_put_console_buffer(string_buf);
        }

        if (cdls != NULL && cdls->cdls_count != 0) {
                string_buf = cfs_trace_get_console_buffer();

                needed = snprintf(string_buf, CFS_TRACE_CONSOLE_BUFFER_SIZE,
                         "Skipped %d previous similar message%s\n",
                         cdls->cdls_count, (cdls->cdls_count > 1) ? "s" : "");

                cfs_print_to_console(&header, mask,
                                 string_buf, needed, file, fn);

                cfs_trace_put_console_buffer(string_buf);
                cdls->cdls_count = 0;
        }

        return 0;
}
示例#3
0
文件: spl-debug.c 项目: harshada/spl
int
spl_debug_vmsg(spl_debug_limit_state_t *cdls, int subsys, int mask,
               const char *file, const char *fn, const int line,
               const char *format1, va_list args, const char *format2, ...)
{
        struct trace_cpu_data   *tcd = NULL;
        struct spl_debug_header header = { 0, };
        struct trace_page       *tage;
        /* string_buf is used only if tcd != NULL, and is always set then */
        char                    *string_buf = NULL;
        char                    *debug_buf;
        int                      known_size;
        int                      needed = 85; /* average message length */
        int                      max_nob;
        va_list                  ap;
        int                      i;
        int                      remain;

        if (strchr(file, '/'))
                file = strrchr(file, '/') + 1;

        trace_set_debug_header(&header, subsys, mask, line, CDEBUG_STACK());

        tcd = trace_get_tcd();
        if (tcd == NULL)
                goto console;

        if (tcd->tcd_shutting_down) {
                trace_put_tcd(tcd);
                tcd = NULL;
                goto console;
        }

        known_size = strlen(file) + 1;
        if (fn)
                known_size += strlen(fn) + 1;

        if (spl_debug_binary)
                known_size += sizeof(header);

        /* '2' used because vsnprintf returns real size required for output
         * _without_ terminating NULL. */
        for (i = 0; i < 2; i++) {
                tage = trace_get_tage(tcd, needed + known_size + 1);
                if (tage == NULL) {
                        if (needed + known_size > PAGE_SIZE)
                                mask |= D_ERROR;

                        trace_put_tcd(tcd);
                        tcd = NULL;
                        goto console;
                }

                string_buf = (char *)page_address(tage->page) +
                             tage->used + known_size;

                max_nob = PAGE_SIZE - tage->used - known_size;
                if (max_nob <= 0) {
                        printk(KERN_EMERG "negative max_nob: %i\n", max_nob);
                        mask |= D_ERROR;
                        trace_put_tcd(tcd);
                        tcd = NULL;
                        goto console;
                }

                needed = 0;
                if (format1) {
                        va_copy(ap, args);
                        needed = vsnprintf(string_buf, max_nob, format1, ap);
                        va_end(ap);
                }

                if (format2) {
                        remain = max_nob - needed;
                        if (remain < 0)
                                remain = 0;

                        va_start(ap, format2);
                        needed += vsnprintf(string_buf+needed, remain, format2, ap);
                        va_end(ap);
                }

                if (needed < max_nob)
                        break;
        }

        header.ph_len = known_size + needed;
        debug_buf = (char *)page_address(tage->page) + tage->used;

        if (spl_debug_binary) {
                memcpy(debug_buf, &header, sizeof(header));
                tage->used += sizeof(header);
                debug_buf += sizeof(header);
        }

        strcpy(debug_buf, file);
        tage->used += strlen(file) + 1;
        debug_buf += strlen(file) + 1;

        if (fn) {
                strcpy(debug_buf, fn);
                tage->used += strlen(fn) + 1;
                debug_buf += strlen(fn) + 1;
        }

        __ASSERT(debug_buf == string_buf);

        tage->used += needed;
        __ASSERT (tage->used <= PAGE_SIZE);

console:
        if ((mask & spl_debug_printk) == 0) {
                /* no console output requested */
                if (tcd != NULL)
                        trace_put_tcd(tcd);
                return 1;
        }

        if (cdls != NULL) {
                if (spl_console_ratelimit && cdls->cdls_next != 0 &&
                    !time_before(cdls->cdls_next, jiffies)) {
                        /* skipping a console message */
                        cdls->cdls_count++;
                        if (tcd != NULL)
                                trace_put_tcd(tcd);
                        return 1;
                }

                if (time_before(cdls->cdls_next + spl_console_max_delay +
                                (10 * HZ), jiffies)) {
                        /* last timeout was a long time ago */
                        cdls->cdls_delay /= spl_console_backoff * 4;
                } else {
                        cdls->cdls_delay *= spl_console_backoff;

                        if (cdls->cdls_delay < spl_console_min_delay)
                                cdls->cdls_delay = spl_console_min_delay;
                        else if (cdls->cdls_delay > spl_console_max_delay)
                                cdls->cdls_delay = spl_console_max_delay;
                }

                /* ensure cdls_next is never zero after it's been seen */
                cdls->cdls_next = (jiffies + cdls->cdls_delay) | 1;
        }

        if (tcd != NULL) {
                trace_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);
                        }
                }
                trace_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" : "");

                trace_print_to_console(&header, mask,
                                 string_buf, needed, file, fn);

                trace_put_console_buffer(string_buf);
                cdls->cdls_count = 0;
        }

        return 0;
}