Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / libcfs / libcfs / winnt / winnt-tracefile.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
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.
11  *
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).
17  *
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
21  *
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
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36
37 #define DEBUG_SUBSYSTEM S_LNET
38 #define LUSTRE_TRACEFILE_PRIVATE
39
40 #include <libcfs/libcfs.h>
41 #include "tracefile.h"
42
43 #ifndef get_cpu
44 #define get_cpu() smp_processor_id()
45 #define put_cpu() do { } while (0)
46 #endif
47
48 /* only define one trace_data type for windows */
49 enum {
50         TCD_TYPE_PASSIVE = 0,
51         TCD_TYPE_DISPATCH,
52         TCD_TYPE_MAX
53 };
54
55 /* percents to share the total debug memory for each type */
56 static unsigned int pages_factor[TCD_TYPE_MAX] = {
57         90,  /* 90% pages for TCD_TYPE_PASSIVE */
58         10   /* 10% pages for TCD_TYPE_DISPATCH */
59 };
60
61 char *trace_console_buffers[NR_CPUS][TCD_TYPE_MAX];
62
63 struct rw_semaphore tracefile_sem;
64
65 int tracefile_init_arch()
66 {
67         int    i;
68         int    j;
69         struct trace_cpu_data *tcd;
70
71         init_rwsem(&tracefile_sem);
72
73         /* initialize trace_data */
74         memset(trace_data, 0, sizeof(trace_data));
75         for (i = 0; i < TCD_TYPE_MAX; i++) {
76                 trace_data[i]=cfs_alloc(sizeof(union trace_data_union)*NR_CPUS,
77                                                           GFP_KERNEL);
78                 if (trace_data[i] == NULL)
79                         goto out;
80         }
81
82         /* arch related info initialized */
83         tcd_for_each(tcd, i, j) {
84                 tcd->tcd_pages_factor = (USHORT) pages_factor[i];
85                 tcd->tcd_type = (USHORT) i;
86                 tcd->tcd_cpu = (USHORT)j;
87         }
88
89         for (i = 0; i < num_possible_cpus(); i++)
90                 for (j = 0; j < TCD_TYPE_MAX; j++) {
91                         trace_console_buffers[i][j] =
92                                 cfs_alloc(TRACE_CONSOLE_BUFFER_SIZE,
93                                           GFP_KERNEL);
94
95                         if (trace_console_buffers[i][j] == NULL)
96                                 goto out;
97                 }
98
99         return 0;
100
101 out:
102         tracefile_fini_arch();
103         printk(KERN_ERR "lnet: No enough memory\n");
104         return -ENOMEM;
105
106 }
107
108 void tracefile_fini_arch()
109 {
110         int    i;
111         int    j;
112
113         for (i = 0; i < num_possible_cpus(); i++) {
114                 for (j = 0; j < TCD_TYPE_MAX; j++) {
115                         if (trace_console_buffers[i][j] != NULL) {
116                                 cfs_free(trace_console_buffers[i][j]);
117                                 trace_console_buffers[i][j] = NULL;
118                         }
119                 }
120         }
121
122         for (i = 0; trace_data[i] != NULL; i++) {
123                 cfs_free(trace_data[i]);
124                 trace_data[i] = NULL;
125         }
126
127         fini_rwsem(&tracefile_sem);
128 }
129
130 void tracefile_read_lock()
131 {
132         down_read(&tracefile_sem);
133 }
134
135 void tracefile_read_unlock()
136 {
137         up_read(&tracefile_sem);
138 }
139
140 void tracefile_write_lock()
141 {
142         down_write(&tracefile_sem);
143 }
144
145 void tracefile_write_unlock()
146 {
147         up_write(&tracefile_sem);
148 }
149
150 char *
151 trace_get_console_buffer(void)
152 {
153         int cpu  = get_cpu();
154         int type = 0;
155         
156         if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
157                 type = TCD_TYPE_DISPATCH;
158         else
159                 type = TCD_TYPE_PASSIVE;
160         return trace_console_buffers[cpu][type];
161 }
162
163 void
164 trace_put_console_buffer(char *buffer)
165 {
166         put_cpu();
167 }
168
169 struct trace_cpu_data *
170 trace_get_tcd(void)
171 {
172         int cpu  = get_cpu();
173         int type = 0;
174         
175         if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
176                 type = TCD_TYPE_DISPATCH;
177         else
178                 type = TCD_TYPE_PASSIVE;
179         return &(*trace_data[type])[cpu].tcd;
180 }
181
182 void
183 trace_put_tcd (struct trace_cpu_data *tcd)
184 {
185         put_cpu();
186 }
187
188 int trace_lock_tcd(struct trace_cpu_data *tcd)
189 {
190         __LASSERT(tcd->tcd_type < TCD_TYPE_MAX);
191         return 1;
192 }
193
194 void trace_unlock_tcd(struct trace_cpu_data *tcd)
195 {
196         __LASSERT(tcd->tcd_type < TCD_TYPE_MAX);
197 }
198
199 int tcd_owns_tage(struct trace_cpu_data *tcd, struct trace_page *tage)
200 {
201         /*
202          * XXX nikita: do NOT call portals_debug_msg() (CDEBUG/ENTRY/EXIT)
203          * from here: this will lead to infinite recursion.
204          */
205         return tcd->tcd_cpu == tage->cpu;
206 }
207
208 void
209 set_ptldebug_header(struct ptldebug_header *header, int subsys, int mask,
210                     const int line, unsigned long stack)
211 {
212         struct timeval tv;
213
214         do_gettimeofday(&tv);
215
216         header->ph_subsys = subsys;
217         header->ph_mask = mask;
218         header->ph_cpu_id = smp_processor_id();
219         header->ph_sec = (__u32)tv.tv_sec;
220         header->ph_usec = tv.tv_usec;
221         header->ph_stack = stack;
222         header->ph_pid = (__u32)(ULONG_PTR)current->pid;
223         header->ph_line_num = line;
224         header->ph_extern_pid = 0;
225         return;
226 }
227
228 void print_to_console(struct ptldebug_header *hdr, int mask, const char *buf,
229                              int len, const char *file, const char *fn)
230 {
231         char *prefix = "Lustre", *ptype = NULL;
232
233         if ((mask & D_EMERG) != 0) {
234                 prefix = "LustreError";
235                 ptype = KERN_EMERG;
236         } else if ((mask & D_ERROR) != 0) {
237                 prefix = "LustreError";
238                 ptype = KERN_ERR;
239         } else if ((mask & D_WARNING) != 0) {
240                 prefix = "Lustre";
241                 ptype = KERN_WARNING;
242         } else if ((mask & (D_CONSOLE | libcfs_printk)) != 0) {
243                 prefix = "Lustre";
244                 ptype = KERN_INFO;
245         }
246
247         if ((mask & D_CONSOLE) != 0) {
248                 printk("%s%s: %.*s", ptype, prefix, len, buf);
249         } else {
250                 printk("%s%s: %d:%d:(%s:%d:%s()) %.*s", ptype, prefix, hdr->ph_pid,
251                        hdr->ph_extern_pid, file, hdr->ph_line_num, fn, len, buf);
252         }
253         return;
254 }
255
256 int trace_max_debug_mb(void)
257 {
258         int  total_mb = (num_physpages >> (20 - CFS_PAGE_SHIFT));
259         
260         return MAX(512, (total_mb * 80)/100);
261 }