Whamcloud - gitweb
d172bff1909930091908d574d3f8947c782e10b8
[fs/lustre-release.git] / lnet / libcfs / winnt / winnt-tracefile.c
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=4:tabstop=4:
3  *
4  *  Copyright (c) 2004 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or modify it under
9  *   the terms of version 2 of the GNU General Public License as published by
10  *   the Free Software Foundation. Lustre is distributed in the hope that it
11  *   will be useful, but WITHOUT ANY WARRANTY; without even the implied
12  *   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *   GNU General Public License for more details. You should have received a
14  *   copy of the GNU General Public License along with Lustre; if not, write
15  *   to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
16  *   USA.
17  */
18
19 #define DEBUG_SUBSYSTEM S_LNET
20 #define LUSTRE_TRACEFILE_PRIVATE
21
22 #include <libcfs/libcfs.h>
23 #include <libcfs/kp30.h>
24 #include "tracefile.h"
25
26 #ifndef get_cpu
27 #define get_cpu() smp_processor_id()
28 #define put_cpu() do { } while (0)
29 #endif
30
31 extern union trace_data_union trace_data[NR_CPUS];
32 extern char *tracefile;
33 extern int64_t tracefile_size;
34
35 event_t     tracefile_event;
36
37 void tracefile_init_arch()
38 {
39         int    i;
40         int    j;
41
42     cfs_init_event(&tracefile_event, TRUE, TRUE);
43
44     memset(trace_console_buffers, 0, sizeof(trace_console_buffers));
45
46         for (i = 0; i < NR_CPUS; i++) {
47                 for (j = 0; j < 1; j++) {
48                         trace_console_buffers[i][j] =
49                                 cfs_alloc(TRACE_CONSOLE_BUFFER_SIZE,
50                                         CFS_ALLOC_ZERO);
51
52                         if (trace_console_buffers[i][j] == NULL) {
53                                 tracefile_fini_arch();
54                                 KsPrint((0, "Can't allocate console message buffer\n"));
55                                 return -ENOMEM;
56                         }
57                 }
58     }
59
60         return 0;
61 }
62
63 void tracefile_fini_arch()
64 {
65         int    i;
66         int    j;
67
68         for (i = 0; i < NR_CPUS; i++) {
69                 for (j = 0; j < 2; j++) {
70                         if (trace_console_buffers[i][j] != NULL) {
71                                 cfs_free(trace_console_buffers[i][j]);
72                                 trace_console_buffers[i][j] = NULL;
73                         }
74         }
75     }
76 }
77
78 void tracefile_read_lock()
79 {
80     cfs_wait_event(&tracefile_event, 0);
81 }
82
83 void tracefile_read_unlock()
84 {
85     cfs_wake_event(&tracefile_event);
86 }
87
88 void tracefile_write_lock()
89 {
90     cfs_wait_event(&tracefile_event, 0);
91 }
92
93 void tracefile_write_unlock()
94 {
95     cfs_wake_event(&tracefile_event);
96 }
97
98 char *
99 trace_get_console_buffer(void)
100 {
101 #pragma message ("is there possible problem with pre-emption ?")
102     int cpu = (int) KeGetCurrentProcessorNumber();
103     return trace_console_buffers[cpu][0];
104 }
105
106 void
107 trace_put_console_buffer(char *buffer)
108 {
109 }
110
111 struct trace_cpu_data *
112 trace_get_tcd(void)
113 {
114 #pragma message("todo: return NULL if in interrupt context")
115
116         int cpu = (int) KeGetCurrentProcessorNumber();
117         return &trace_data[cpu].tcd;
118 }
119
120 void
121 trace_put_tcd (struct trace_cpu_data *tcd, unsigned long flags)
122 {
123 }
124
125 void
126 set_ptldebug_header(struct ptldebug_header *header, int subsys, int mask,
127                     const int line, unsigned long stack)
128 {
129         struct timeval tv;
130
131         do_gettimeofday(&tv);
132
133         header->ph_subsys = subsys;
134         header->ph_mask = mask;
135         header->ph_cpu_id = smp_processor_id();
136         header->ph_sec = (__u32)tv.tv_sec;
137         header->ph_usec = tv.tv_usec;
138         header->ph_stack = stack;
139         header->ph_pid = current->pid;
140         header->ph_line_num = line;
141         header->ph_extern_pid = 0;
142         return;
143 }
144
145 void print_to_console(struct ptldebug_header *hdr, int mask, const char *buf,
146                                   int len, const char *file, const char *fn)
147 {
148         char *prefix = NULL, *ptype = NULL;
149
150         if ((mask & D_EMERG) != 0) {
151                 prefix = "LustreError";
152                 ptype = KERN_EMERG;
153         } else if ((mask & D_ERROR) != 0) {
154                 prefix = "LustreError";
155                 ptype = KERN_ERR;
156         } else if ((mask & D_WARNING) != 0) {
157                 prefix = "Lustre";
158                 ptype = KERN_WARNING;
159         } else if ((mask & libcfs_printk) != 0 || (mask & D_CONSOLE)) {
160                 prefix = "Lustre";
161                 ptype = KERN_INFO;
162         }
163
164         if ((mask & D_CONSOLE) != 0) {
165                 printk("%s%s: %s", ptype, prefix, buf);
166         } else {
167                 printk("%s%s: %d:%d:(%s:%d:%s()) %s", ptype, prefix, hdr->ph_pid,
168                        hdr->ph_extern_pid, file, hdr->ph_line_num, fn, buf);
169         }
170         return;
171 }
172
173 int tcd_owns_tage(struct trace_cpu_data *tcd, struct trace_page *tage)
174 {
175         return 1;
176 }
177
178
179 int trace_write_daemon_file(struct file *file, const char *buffer,
180                             unsigned long count, void *data)
181 {
182         char *name;
183         unsigned long off;
184         int rc;
185
186         name =cfs_alloc(count + 1, 0);
187         if (name == NULL)
188                 return -ENOMEM;
189
190         if (copy_from_user((void *)name, (void*)buffer, count)) {
191                 rc = -EFAULT;
192                 goto out;
193         }
194
195         /* be nice and strip out trailing '\n' */
196         for (off = count ; off > 2 && isspace(name[off - 1]); off--)
197                 ;
198
199         name[off] = '\0';
200
201         tracefile_write_lock();
202         if (strcmp(name, "stop") == 0) {
203                 tracefile = NULL;
204                 trace_stop_thread();
205                 goto out_sem;
206         } else if (strncmp(name, "size=", 5) == 0) {
207                 tracefile_size = simple_strtoul(name + 5, NULL, 0);
208                 if (tracefile_size < 10 || tracefile_size > 20480)
209                         tracefile_size = TRACEFILE_SIZE;
210                 else
211                         tracefile_size <<= 20;
212                 goto out_sem;
213         }
214
215         if (tracefile != NULL)
216                 cfs_free(tracefile);
217
218         tracefile = name;
219         name = NULL;
220         printk(KERN_INFO "Lustre: debug daemon will attempt to start writing "
221                "to %s (%lukB max)\n", tracefile, (long)(tracefile_size >> 10));
222
223         trace_start_thread();
224 out_sem:
225     tracefile_write_unlock();
226 out:
227     if (name != NULL)
228             cfs_free(name);
229         return count;
230 }
231
232 int trace_read_daemon_file(char *page, char **start, off_t off, int count,
233                            int *eof, void *data)
234 {
235         int rc;
236
237         tracefile_read_lock();
238         rc = snprintf(page, count, "%s", tracefile);
239         tracefile_read_unlock();
240
241         return rc;
242 }
243
244 int trace_write_debug_mb(struct file *file, const char *buffer,
245                          unsigned long count, void *data)
246 {
247         char string[32];
248         int i;
249         unsigned max;
250
251         if (count >= sizeof(string)) {
252                 printk(KERN_ERR "Lustre: value too large (length %lu bytes)\n",
253                        count);
254                 return -EOVERFLOW;
255         }
256
257         if (copy_from_user((void *)string, (void *)buffer, count))
258                 return -EFAULT;
259
260         max = simple_strtoul(string, NULL, 0);
261         if (max == 0)
262                 return -EINVAL;
263
264         if (max > (num_physpages >> (20 - 2 - CFS_PAGE_SHIFT)) / 5 || max >= 512) {
265                 printk(KERN_ERR "Lustre: Refusing to set debug buffer size to "
266                        "%dMB, which is more than 80%% of available RAM (%lu)\n",
267                        max, (num_physpages >> (20 - 2 - CFS_PAGE_SHIFT)) / 5);
268                 return -EINVAL;
269         }
270
271         max /= smp_num_cpus;
272
273         for (i = 0; i < NR_CPUS; i++) {
274                 struct trace_cpu_data *tcd;
275                 tcd = &trace_data[i].tcd;
276                 tcd->tcd_max_pages = max << (20 - CFS_PAGE_SHIFT);
277         }
278         return count;
279 }
280
281 int trace_read_debug_mb(char *page, char **start, off_t off, int count,
282                         int *eof, void *data)
283 {
284         struct trace_cpu_data *tcd;
285         int rc;
286
287         tcd = trace_get_tcd();
288         LASSERT (tcd != NULL);
289         rc = snprintf(page, count, "%lu\n",
290                       (tcd->tcd_max_pages >> (20 - CFS_PAGE_SHIFT)) * smp_num_cpus);
291         trace_put_tcd(tcd);
292         return rc;
293 }
294
295 void
296 trace_call_on_all_cpus(void (*fn)(void *arg), void *arg)
297 {
298 #error "tbd"
299 }
300