Whamcloud - gitweb
063cb80bf2f0e58bf6402a8bde420f3c4c8910d8
[fs/lustre-release.git] / libcfs / libcfs / darwin / darwin-tracefile.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
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.
9  *
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).
15  *
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
19  *
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
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  */
30 /*
31  * This file is part of Lustre, http://www.lustre.org/
32  * Lustre is a trademark of Sun Microsystems, Inc.
33  */
34
35 #define DEBUG_SUBSYSTEM S_LNET
36 #define LUSTRE_TRACEFILE_PRIVATE
37 #include <libcfs/libcfs.h>
38 #include "tracefile.h"
39
40 /*
41  * We can't support smp tracefile currently.
42  * Everything is put on one cpu.
43  */
44
45 #define M_TCD_MAX_PAGES (128 * 1280)
46
47 static long max_permit_mb = (64 * 1024);
48
49 spinlock_t trace_cpu_serializer;
50
51 /*
52  * thread currently executing tracefile code or NULL if none does. Used to
53  * detect recursive calls to libcfs_debug_msg().
54  */
55 static thread_t trace_owner = NULL;
56
57 extern int get_preemption_level(void);
58 extern atomic_t tage_allocated;
59
60 struct rw_semaphore tracefile_sem;
61
62 int tracefile_init_arch() {
63     init_rwsem(&tracefile_sem);
64 #error "Todo: initialise per-cpu console buffers"
65     return 0;
66 }
67
68 void tracefile_fini_arch() {
69     fini_rwsem(&tracefile_sem);
70 }
71
72 void tracefile_read_lock() {
73     down_read(&tracefile_sem);
74 }
75
76 void tracefile_read_unlock() {
77     up_read(&tracefile_sem);
78 }
79
80 void tracefile_write_lock() {
81     down_write(&tracefile_sem);
82 }
83
84 void tracefile_write_unlock() {
85     up_write(&tracefile_sem);
86 }
87
88 char *trace_get_console_buffer(void)
89 {
90 #error "todo: return a per-cpu/interrupt console buffer and disable pre-emption"
91 }
92
93 void trace_put_console_buffer(char *buffer)
94 {
95 #error "todo: re-enable pre-emption"
96 }
97
98 struct trace_cpu_data *trace_get_tcd(void)
99 {
100         struct trace_cpu_data *tcd;
101         int nr_pages;
102         struct list_head pages;
103
104         /*
105          * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
106          * from here: this will lead to infinite recursion.
107          */
108
109         /*
110          * debugging check for recursive call to libcfs_debug_msg()
111          */
112         if (trace_owner == current_thread()) {
113                 /*
114                  * Cannot assert here.
115                  */
116                 printk(KERN_EMERG "recursive call to %s", __FUNCTION__);
117                 /*
118                  * "The death of God left the angels in a strange position."
119                  */
120                 cfs_enter_debugger();
121         }
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);
126         else
127                 nr_pages = 0;
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);
132         return tcd;
133 }
134
135 extern void raw_page_death_row_clean(void);
136
137 void __trace_put_tcd(struct trace_cpu_data *tcd)
138 {
139         /*
140          * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
141          * from here: this will lead to infinite recursion.
142          */
143         LASSERT(trace_owner == current_thread());
144         trace_owner = NULL;
145         spin_unlock(&trace_cpu_serializer);
146         if (get_preemption_level() == 0)
147                 /* purge all pending pages */
148                 raw_page_death_row_clean();
149 }
150
151 int tcd_owns_tage(struct trace_cpu_data *tcd, struct trace_page *tage)
152 {
153         /*
154          * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
155          * from here: this will lead to infinite recursion.
156          */
157         /* XNU has global tcd, and all pages are owned by it */
158         return 1;
159 }
160
161 void
162 set_ptldebug_header(struct ptldebug_header *header, int subsys, int mask,
163                     const int line, unsigned long stack)
164 {
165         struct timeval tv;
166         
167         /*
168          * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
169          * from here: this will lead to infinite recursion.
170          */
171         do_gettimeofday(&tv);
172         header->ph_subsys = subsys;
173         header->ph_mask = mask;
174         header->ph_cpu_id = smp_processor_id();
175         header->ph_type = 0;
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();
182 }
183
184 void print_to_console(struct ptldebug_header *hdr, int mask, const char *buf,
185                       int len, const char *file, const char *fn)
186 {
187         char *prefix = "Lustre", *ptype = KERN_INFO;
188
189         /*
190          * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
191          * from here: this will lead to infinite recursion.
192          */
193         if ((mask & D_EMERG) != 0) {
194                 prefix = "LustreError";
195                 ptype = KERN_EMERG;
196         } else if ((mask & D_ERROR) != 0) {
197                 prefix = "LustreError";
198                 ptype = KERN_ERR;
199         } else if ((mask & D_WARNING) != 0) {
200                 prefix = "Lustre";
201                 ptype = KERN_WARNING;
202         } else if ((mask & libcfs_printk) != 0 || (mask & D_CONSOLE)) {
203                 prefix = "Lustre";
204                 ptype = KERN_INFO;
205         }
206
207         if ((mask & D_CONSOLE) != 0) {
208                 printk("%s%s: %.*s", ptype, prefix, len, buf);
209         } else {
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);
213         }
214 }
215
216 int trace_max_debug_mb(void)
217 {
218         return max_permit_mb;
219 }