1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
37 #define DEBUG_SUBSYSTEM S_LNET
38 #define LUSTRE_TRACEFILE_PRIVATE
39 #include <libcfs/libcfs.h>
40 #include "tracefile.h"
43 * We can't support smp tracefile currently.
44 * Everything is put on one cpu.
47 #define M_TCD_MAX_PAGES (128 * 1280)
49 static long max_permit_mb = (64 * 1024);
51 spinlock_t trace_cpu_serializer;
54 * thread currently executing tracefile code or NULL if none does. Used to
55 * detect recursive calls to libcfs_debug_msg().
57 static thread_t trace_owner = NULL;
59 extern int get_preemption_level(void);
60 extern atomic_t tage_allocated;
62 struct rw_semaphore tracefile_sem;
64 int tracefile_init_arch() {
65 init_rwsem(&tracefile_sem);
66 #error "Todo: initialise per-cpu console buffers"
70 void tracefile_fini_arch() {
71 fini_rwsem(&tracefile_sem);
74 void tracefile_read_lock() {
75 down_read(&tracefile_sem);
78 void tracefile_read_unlock() {
79 up_read(&tracefile_sem);
82 void tracefile_write_lock() {
83 down_write(&tracefile_sem);
86 void tracefile_write_unlock() {
87 up_write(&tracefile_sem);
90 char *trace_get_console_buffer(void)
92 #error "todo: return a per-cpu/interrupt console buffer and disable pre-emption"
95 void trace_put_console_buffer(char *buffer)
97 #error "todo: re-enable pre-emption"
100 struct trace_cpu_data *trace_get_tcd(void)
102 struct trace_cpu_data *tcd;
104 struct list_head pages;
107 * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
108 * from here: this will lead to infinite recursion.
112 * debugging check for recursive call to libcfs_debug_msg()
114 if (trace_owner == current_thread()) {
116 * Cannot assert here.
118 printk(KERN_EMERG "recursive call to %s", __FUNCTION__);
120 * "The death of God left the angels in a strange position."
122 cfs_enter_debugger();
124 tcd = &trace_data[0].tcd;
125 CFS_INIT_LIST_HEAD(&pages);
126 if (get_preemption_level() == 0)
127 nr_pages = trace_refill_stock(tcd, CFS_ALLOC_STD, &pages);
130 spin_lock(&trace_cpu_serializer);
131 trace_owner = current_thread();
132 tcd->tcd_cur_stock_pages += nr_pages;
133 list_splice(&pages, &tcd->tcd_stock_pages);
137 extern void raw_page_death_row_clean(void);
139 void __trace_put_tcd(struct trace_cpu_data *tcd)
142 * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
143 * from here: this will lead to infinite recursion.
145 LASSERT(trace_owner == current_thread());
147 spin_unlock(&trace_cpu_serializer);
148 if (get_preemption_level() == 0)
149 /* purge all pending pages */
150 raw_page_death_row_clean();
153 int tcd_owns_tage(struct trace_cpu_data *tcd, struct trace_page *tage)
156 * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
157 * from here: this will lead to infinite recursion.
159 /* XNU has global tcd, and all pages are owned by it */
164 set_ptldebug_header(struct ptldebug_header *header, int subsys, int mask,
165 const int line, unsigned long stack)
170 * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
171 * from here: this will lead to infinite recursion.
173 do_gettimeofday(&tv);
174 header->ph_subsys = subsys;
175 header->ph_mask = mask;
176 header->ph_cpu_id = cfs_smp_processor_id();
178 header->ph_sec = (__u32)tv.tv_sec;
179 header->ph_usec = tv.tv_usec;
180 header->ph_stack = stack;
181 header->ph_pid = cfs_curproc_pid();
182 header->ph_line_num = line;
183 header->ph_extern_pid = (__u32)current_thread();
186 void print_to_console(struct ptldebug_header *hdr, int mask, const char *buf,
187 int len, const char *file, const char *fn)
189 char *prefix = "Lustre", *ptype = KERN_INFO;
192 * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
193 * from here: this will lead to infinite recursion.
195 if ((mask & D_EMERG) != 0) {
196 prefix = "LustreError";
198 } else if ((mask & D_ERROR) != 0) {
199 prefix = "LustreError";
201 } else if ((mask & D_WARNING) != 0) {
203 ptype = KERN_WARNING;
204 } else if ((mask & libcfs_printk) != 0 || (mask & D_CONSOLE)) {
209 if ((mask & D_CONSOLE) != 0) {
210 printk("%s%s: %.*s", ptype, prefix, len, buf);
212 printk("%s%s: %d:%d:(%s:%d:%s()) %*s",
213 ptype, prefix, hdr->ph_pid, hdr->ph_extern_pid,
214 file, hdr->ph_line_num, fn, len, buf);
218 int trace_max_debug_mb(void)
220 return max_permit_mb;