tracefile.c

来自「lustre 1.6.5 source code」· C语言 代码 · 共 1,115 行 · 第 1/3 页

C
1,115
字号
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * * Copyright (C) 2004 Cluster File Systems, Inc. *   Author: Zach Brown <zab@clusterfs.com> *   Author: Phil Schwan <phil@clusterfs.com> * *   This file is part of Lustre, http://www.lustre.org. * *   Lustre is free software; you can redistribute it and/or *   modify it under the terms of version 2 of the GNU General Public *   License as published by the Free Software Foundation. * *   Lustre is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with Lustre; if not, write to the Free Software *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#define DEBUG_SUBSYSTEM S_LNET#define LUSTRE_TRACEFILE_PRIVATE#include "tracefile.h"#include <libcfs/kp30.h>#include <libcfs/libcfs.h>/* XXX move things up to the top, comment */union trace_data_union (*trace_data[TCD_MAX_TYPES])[NR_CPUS] __cacheline_aligned;char tracefile[TRACEFILE_NAME_SIZE];long long tracefile_size = TRACEFILE_SIZE;static struct tracefiled_ctl trace_tctl;struct semaphore trace_thread_sem;static int thread_running = 0;atomic_t tage_allocated = ATOMIC_INIT(0);static void put_pages_on_tcd_daemon_list(struct page_collection *pc,                                         struct trace_cpu_data *tcd);static inline struct trace_page *tage_from_list(struct list_head *list){        return list_entry(list, struct trace_page, linkage);}static struct trace_page *tage_alloc(int gfp){        cfs_page_t        *page;        struct trace_page *tage;        /*         * Don't spam console with allocation failures: they will be reported         * by upper layer anyway.         */        gfp |= CFS_ALLOC_NOWARN;        page = cfs_alloc_page(gfp);        if (page == NULL)                return NULL;        tage = cfs_alloc(sizeof(*tage), gfp);        if (tage == NULL) {                cfs_free_page(page);                return NULL;        }        tage->page = page;        atomic_inc(&tage_allocated);        return tage;}static void tage_free(struct trace_page *tage){        __LASSERT(tage != NULL);        __LASSERT(tage->page != NULL);        cfs_free_page(tage->page);        cfs_free(tage);        atomic_dec(&tage_allocated);}static void tage_to_tail(struct trace_page *tage, struct list_head *queue){        __LASSERT(tage != NULL);        __LASSERT(queue != NULL);        list_move_tail(&tage->linkage, queue);}int trace_refill_stock(struct trace_cpu_data *tcd, int gfp,                       struct list_head *stock){        int i;        /*         * XXX nikita: do NOT call portals_debug_msg() (CDEBUG/ENTRY/EXIT)         * from here: this will lead to infinite recursion.         */        for (i = 0; i + tcd->tcd_cur_stock_pages < TCD_STOCK_PAGES ; ++ i) {                struct trace_page *tage;                tage = tage_alloc(gfp);                if (tage == NULL)                        break;                list_add_tail(&tage->linkage, stock);        }        return i;}/* return a page that has 'len' bytes left at the end */static struct trace_page *trace_get_tage_try(struct trace_cpu_data *tcd,                                             unsigned long len){        struct trace_page *tage;        if (tcd->tcd_cur_pages > 0) {                __LASSERT(!list_empty(&tcd->tcd_pages));                tage = tage_from_list(tcd->tcd_pages.prev);                if (tage->used + len <= CFS_PAGE_SIZE)                        return tage;        }        if (tcd->tcd_cur_pages < tcd->tcd_max_pages) {                if (tcd->tcd_cur_stock_pages > 0) {                        tage = tage_from_list(tcd->tcd_stock_pages.prev);                        -- tcd->tcd_cur_stock_pages;                        list_del_init(&tage->linkage);                } else {                        tage = tage_alloc(CFS_ALLOC_ATOMIC);                        if (tage == NULL) {                                printk(KERN_WARNING                                       "failure to allocate a tage (%ld)\n",                                       tcd->tcd_cur_pages);                                return NULL;                        }                }                tage->used = 0;                tage->cpu = smp_processor_id();                tage->type = tcd->tcd_type;                list_add_tail(&tage->linkage, &tcd->tcd_pages);                tcd->tcd_cur_pages++;                if (tcd->tcd_cur_pages > 8 && thread_running) {                        struct tracefiled_ctl *tctl = &trace_tctl;                        /*                         * wake up tracefiled to process some pages.                         */                        cfs_waitq_signal(&tctl->tctl_waitq);                }                return tage;        }        return NULL;}static void tcd_shrink(struct trace_cpu_data *tcd){        int pgcount = tcd->tcd_cur_pages / 10;        struct page_collection pc;        struct trace_page *tage;        struct trace_page *tmp;	/*	 * XXX nikita: do NOT call portals_debug_msg() (CDEBUG/ENTRY/EXIT)	 * from here: this will lead to infinite recursion.	 */        printk(KERN_WARNING "debug daemon buffer overflowed; discarding"               " 10%% of pages (%d of %ld)\n", pgcount + 1, tcd->tcd_cur_pages);        CFS_INIT_LIST_HEAD(&pc.pc_pages);        spin_lock_init(&pc.pc_lock);        list_for_each_entry_safe(tage, tmp, &tcd->tcd_pages, linkage) {                if (pgcount-- == 0)                        break;                list_move_tail(&tage->linkage, &pc.pc_pages);                tcd->tcd_cur_pages--;        }        put_pages_on_tcd_daemon_list(&pc, tcd);}/* return a page that has 'len' bytes left at the end */static struct trace_page *trace_get_tage(struct trace_cpu_data *tcd,                                         unsigned long len){        struct trace_page *tage;	/*	 * XXX nikita: do NOT call portals_debug_msg() (CDEBUG/ENTRY/EXIT)	 * from here: this will lead to infinite recursion.	 */        if (len > CFS_PAGE_SIZE) {                printk(KERN_ERR                       "cowardly refusing to write %lu bytes in a page\n", len);                return NULL;        }        tage = trace_get_tage_try(tcd, len);        if (tage != NULL)                return tage;        if (thread_running)                tcd_shrink(tcd);        if (tcd->tcd_cur_pages > 0) {                tage = tage_from_list(tcd->tcd_pages.next);                tage->used = 0;                tage_to_tail(tage, &tcd->tcd_pages);        }        return tage;}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 trace_cpu_data   *tcd = NULL;        struct ptldebug_header   header;        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                      depth;        int                      i;        int                      remain;        if (strchr(file, '/'))                file = strrchr(file, '/') + 1;        set_ptldebug_header(&header, subsys, mask, line, CDEBUG_STACK());        tcd = trace_get_tcd();        if (tcd == NULL)                /* arch may not log in IRQ context */                goto console;        if (tcd->tcd_shutting_down) {                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 = trace_get_tage(tcd, needed + known_size + 1);                if (tage == NULL) {                        if (needed + known_size > CFS_PAGE_SIZE)                                mask |= D_ERROR;                        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(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) /* well. printing ok.. */                        break;        }	        if (*(string_buf+needed-1) != '\n')                printk(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)                        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)                                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)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?