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
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
31 * This file is part of Lustre, http://www.lustre.org/
32 * Lustre is a trademark of Sun Microsystems, Inc.
35 #define DEBUG_SUBSYSTEM S_LNET
36 #define LUSTRE_TRACEFILE_PRIVATE
37 #include <libcfs/libcfs.h>
38 #include "tracefile.h"
41 * We can't support smp tracefile currently.
42 * Everything is put on one cpu.
45 #define M_TCD_MAX_PAGES (128 * 1280)
47 static long max_permit_mb = (64 * 1024);
49 spinlock_t trace_cpu_serializer;
52 * thread currently executing tracefile code or NULL if none does. Used to
53 * detect recursive calls to libcfs_debug_msg().
55 static thread_t trace_owner = NULL;
57 extern int get_preemption_level(void);
58 extern atomic_t tage_allocated;
60 struct rw_semaphore tracefile_sem;
62 int tracefile_init_arch() {
63 init_rwsem(&tracefile_sem);
64 #error "Todo: initialise per-cpu console buffers"
68 void tracefile_fini_arch() {
69 fini_rwsem(&tracefile_sem);
72 void tracefile_read_lock() {
73 down_read(&tracefile_sem);
76 void tracefile_read_unlock() {
77 up_read(&tracefile_sem);
80 void tracefile_write_lock() {
81 down_write(&tracefile_sem);
84 void tracefile_write_unlock() {
85 up_write(&tracefile_sem);
88 char *trace_get_console_buffer(void)
90 #error "todo: return a per-cpu/interrupt console buffer and disable pre-emption"
93 void trace_put_console_buffer(char *buffer)
95 #error "todo: re-enable pre-emption"
98 struct trace_cpu_data *trace_get_tcd(void)
100 struct trace_cpu_data *tcd;
102 struct list_head pages;
105 * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
106 * from here: this will lead to infinite recursion.
110 * debugging check for recursive call to libcfs_debug_msg()
112 if (trace_owner == current_thread()) {
114 * Cannot assert here.
116 printk(KERN_EMERG "recursive call to %s", __FUNCTION__);
118 * "The death of God left the angels in a strange position."
120 cfs_enter_debugger();
122 tcd = &trace_data[0].tcd;
123 CFS_INIT_LIST_HEAD(&pages);
124 if (get_preemption_level() == 0)
125 nr_pages = trace_refill_stock(tcd, GFP_IOFS, &pages);
128 spin_lock(&trace_cpu_serializer);
129 trace_owner = current_thread();
130 tcd->tcd_cur_stock_pages += nr_pages;
131 list_splice(&pages, &tcd->tcd_stock_pages);
135 extern void raw_page_death_row_clean(void);
137 void __trace_put_tcd(struct trace_cpu_data *tcd)
140 * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
141 * from here: this will lead to infinite recursion.
143 LASSERT(trace_owner == current_thread());
145 spin_unlock(&trace_cpu_serializer);
146 if (get_preemption_level() == 0)
147 /* purge all pending pages */
148 raw_page_death_row_clean();
151 int tcd_owns_tage(struct trace_cpu_data *tcd, struct trace_page *tage)
154 * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
155 * from here: this will lead to infinite recursion.
157 /* XNU has global tcd, and all pages are owned by it */
162 set_ptldebug_header(struct ptldebug_header *header, int subsys, int mask,
163 const int line, unsigned long stack)
168 * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
169 * from here: this will lead to infinite recursion.
171 do_gettimeofday(&tv);
172 header->ph_subsys = subsys;
173 header->ph_mask = mask;
174 header->ph_cpu_id = cfs_smp_processor_id();
176 header->ph_sec = (__u32)tv.tv_sec;
177 header->ph_usec = tv.tv_usec;
178 header->ph_stack = stack;
179 header->ph_pid = cfs_curproc_pid();
180 header->ph_line_num = line;
181 header->ph_extern_pid = (__u32)current_thread();
184 void print_to_console(struct ptldebug_header *hdr, int mask, const char *buf,
185 int len, const char *file, const char *fn)
187 char *prefix = "Lustre", *ptype = KERN_INFO;
190 * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
191 * from here: this will lead to infinite recursion.
193 if ((mask & D_EMERG) != 0) {
194 prefix = "LustreError";
196 } else if ((mask & D_ERROR) != 0) {
197 prefix = "LustreError";
199 } else if ((mask & D_WARNING) != 0) {
201 ptype = KERN_WARNING;
202 } else if ((mask & libcfs_printk) != 0 || (mask & D_CONSOLE)) {
207 if ((mask & D_CONSOLE) != 0) {
208 printk("%s%s: %.*s", ptype, prefix, len, buf);
210 printk("%s%s: %d:%d:(%s:%d:%s()) %*s",
211 ptype, prefix, hdr->ph_pid, hdr->ph_extern_pid,
212 file, hdr->ph_line_num, fn, len, buf);
216 int trace_max_debug_mb(void)
218 return max_permit_mb;