2 #define DEBUG_SUBSYSTEM S_LNET
3 #define LUSTRE_TRACEFILE_PRIVATE
4 #include <libcfs/libcfs.h>
5 #include <libcfs/kp30.h>
9 * We can't support smp tracefile currently.
10 * Everything is put on one cpu.
13 #define M_TCD_MAX_PAGES (128 * 1280)
14 extern union trace_data_union trace_data[NR_CPUS];
15 extern char *tracefile;
16 extern long long tracefile_size;
17 extern int trace_start_thread(void);
18 extern void trace_stop_thread(void);
20 long max_debug_mb = M_TCD_MAX_PAGES;
21 static long max_permit_mb = (64 * 1024);
23 spinlock_t trace_cpu_serializer;
26 * thread currently executing tracefile code or NULL if none does. Used to
27 * detect recursive calls to libcfs_debug_msg().
29 static thread_t trace_owner = NULL;
31 extern int get_preemption_level(void);
32 extern atomic_t tage_allocated;
34 struct rw_semaphore tracefile_sem;
36 int tracefile_init_arch() {
37 init_rwsem(&tracefile_sem);
38 #error "Todo: initialise per-cpu console buffers"
42 void tracefile_fini_arch() {
45 void tracefile_read_lock() {
46 down_read(&tracefile_sem);
49 void tracefile_read_unlock() {
50 up_read(&tracefile_sem);
53 void tracefile_write_lock() {
54 down_write(&tracefile_sem);
57 void tracefile_write_unlock() {
58 up_write(&tracefile_sem);
61 char *trace_get_console_buffer(void)
63 #error "todo: return a per-cpu/interrupt console buffer and disable pre-emption"
66 void trace_put_console_buffer(char *buffer)
68 #error "todo: re-enable pre-emption"
71 struct trace_cpu_data *trace_get_tcd(void)
73 struct trace_cpu_data *tcd;
75 struct list_head pages;
78 * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
79 * from here: this will lead to infinite recursion.
83 * debugging check for recursive call to libcfs_debug_msg()
85 if (trace_owner == current_thread()) {
89 printk(KERN_EMERG "recursive call to %s", __FUNCTION__);
91 * "The death of God left the angels in a strange position."
95 tcd = &trace_data[0].tcd;
96 CFS_INIT_LIST_HEAD(&pages);
97 if (get_preemption_level() == 0)
98 nr_pages = trace_refill_stock(tcd, CFS_ALLOC_STD, &pages);
101 spin_lock(&trace_cpu_serializer);
102 trace_owner = current_thread();
103 tcd->tcd_cur_stock_pages += nr_pages;
104 list_splice(&pages, &tcd->tcd_stock_pages);
108 extern void raw_page_death_row_clean(void);
110 void __trace_put_tcd(struct trace_cpu_data *tcd)
113 * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
114 * from here: this will lead to infinite recursion.
116 LASSERT(trace_owner == current_thread());
118 spin_unlock(&trace_cpu_serializer);
119 if (get_preemption_level() == 0)
120 /* purge all pending pages */
121 raw_page_death_row_clean();
124 int tcd_owns_tage(struct trace_cpu_data *tcd, struct trace_page *tage)
127 * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
128 * from here: this will lead to infinite recursion.
130 /* XNU has global tcd, and all pages are owned by it */
135 set_ptldebug_header(struct ptldebug_header *header, int subsys, int mask,
136 const int line, unsigned long stack)
141 * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
142 * from here: this will lead to infinite recursion.
144 do_gettimeofday(&tv);
145 header->ph_subsys = subsys;
146 header->ph_mask = mask;
147 header->ph_cpu_id = smp_processor_id();
148 header->ph_sec = (__u32)tv.tv_sec;
149 header->ph_usec = tv.tv_usec;
150 header->ph_stack = stack;
151 header->ph_pid = cfs_curproc_pid();
152 header->ph_line_num = line;
153 header->ph_extern_pid = (__u32)current_thread();
156 void print_to_console(struct ptldebug_header *hdr, int mask, const char *buf,
157 int len, const char *file, const char *fn)
159 char *prefix = "Lustre", *ptype = KERN_INFO;
162 * XXX nikita: do NOT call libcfs_debug_msg() (CDEBUG/ENTRY/EXIT)
163 * from here: this will lead to infinite recursion.
165 if ((mask & D_EMERG) != 0) {
166 prefix = "LustreError";
168 } else if ((mask & D_ERROR) != 0) {
169 prefix = "LustreError";
171 } else if ((mask & D_WARNING) != 0) {
173 ptype = KERN_WARNING;
174 } else if ((mask & libcfs_printk) != 0 || (mask & D_CONSOLE)) {
179 if ((mask & D_CONSOLE) != 0) {
180 printk("%s%s: %.*s", ptype, prefix, len, buf);
182 printk("%s%s: %d:%d:(%s:%d:%s()) %*s",
183 ptype, prefix, hdr->ph_pid, hdr->ph_extern_pid,
184 file, hdr->ph_line_num, fn, len, buf);
189 * Sysctl handle of libcfs
191 #define MAX_TRACEFILE_PATH_LEN 256
192 int cfs_trace_daemon SYSCTL_HANDLER_ARGS
197 if (req->newptr == USER_ADDR_NULL) {
200 error = sysctl_handle_string(oidp, tracefile, 0, req);
202 error = sysctl_handle_string(oidp, "NA", 0, req);
207 /* now hanle write requests */
208 MALLOC(name, char *, MAX_TRACEFILE_PATH_LEN + 1, M_TEMP, M_WAITOK | M_ZERO);
212 tracefile_write_lock();
213 error = sysctl_handle_string(oidp, name, MAX_TRACEFILE_PATH_LEN + 1, req);
215 if (strcmp(name, "stop") == 0) {
216 /* stop tracefile daemon */
220 }else if (strncmp(name, "size=", 5) == 0) {
221 tracefile_size = simple_strtoul(name + 5, NULL, 0);
222 if (tracefile_size < 10 || tracefile_size > 20480)
223 tracefile_size = TRACEFILE_SIZE;
225 tracefile_size <<= 20;
229 if (name[0] != '/') {
233 if (tracefile != NULL)
237 trace_start_thread();
239 /* Something was wrong with the write request */
240 printf("sysctl debug daemon failed: %d.\n", error);
246 tracefile_write_unlock();
249 #undef MAX_TRACEFILE_PATH_LEN
252 int cfs_debug_mb SYSCTL_HANDLER_ARGS
257 error = sysctl_handle_long(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
258 if (!error && req->newptr != USER_ADDR_NULL) {
259 /* We have a new value stored in the standard location */
260 if (max_debug_mb <= 0)
262 if (max_debug_mb > max_permit_mb) {
263 printf("sysctl debug_mb is too big: %d.\n", max_debug_mb);
266 for (i = 0; i < NR_CPUS; i++) {
267 struct trace_cpu_data *tcd;
268 tcd = &trace_data[i].tcd;
269 tcd->tcd_max_pages = max_debug_mb;
271 } else if (req->newptr != USER_ADDR_NULL) {
272 /* Something was wrong with the write request */
273 printf ("sysctl debug_mb fault: %d.\n", error);
280 trace_call_on_all_cpus(void (*fn)(void *arg), void *arg)