Commit | Line | Data |
---|---|---|
d7e09d03 PT |
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 | * Copyright (c) 2012, Intel Corporation. | |
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 | ||
9fdaf8c0 | 40 | #include "../../../include/linux/libcfs/libcfs.h" |
d7e09d03 PT |
41 | #include "tracefile.h" |
42 | ||
43 | /* percents to share the total debug memory for each type */ | |
44 | static unsigned int pages_factor[CFS_TCD_TYPE_MAX] = { | |
45 | 80, /* 80% pages for CFS_TCD_TYPE_PROC */ | |
46 | 10, /* 10% pages for CFS_TCD_TYPE_SOFTIRQ */ | |
47 | 10 /* 10% pages for CFS_TCD_TYPE_IRQ */ | |
48 | }; | |
49 | ||
50 | char *cfs_trace_console_buffers[NR_CPUS][CFS_TCD_TYPE_MAX]; | |
51 | ||
52 | struct rw_semaphore cfs_tracefile_sem; | |
53 | ||
7d46a21a | 54 | int cfs_tracefile_init_arch(void) |
d7e09d03 PT |
55 | { |
56 | int i; | |
57 | int j; | |
58 | struct cfs_trace_cpu_data *tcd; | |
59 | ||
60 | init_rwsem(&cfs_tracefile_sem); | |
61 | ||
62 | /* initialize trace_data */ | |
63 | memset(cfs_trace_data, 0, sizeof(cfs_trace_data)); | |
64 | for (i = 0; i < CFS_TCD_TYPE_MAX; i++) { | |
65 | cfs_trace_data[i] = | |
66 | kmalloc(sizeof(union cfs_trace_data_union) * | |
67 | num_possible_cpus(), GFP_KERNEL); | |
68 | if (cfs_trace_data[i] == NULL) | |
69 | goto out; | |
70 | ||
71 | } | |
72 | ||
73 | /* arch related info initialized */ | |
74 | cfs_tcd_for_each(tcd, i, j) { | |
75 | spin_lock_init(&tcd->tcd_lock); | |
76 | tcd->tcd_pages_factor = pages_factor[i]; | |
77 | tcd->tcd_type = i; | |
78 | tcd->tcd_cpu = j; | |
79 | } | |
80 | ||
81 | for (i = 0; i < num_possible_cpus(); i++) | |
82 | for (j = 0; j < 3; j++) { | |
83 | cfs_trace_console_buffers[i][j] = | |
84 | kmalloc(CFS_TRACE_CONSOLE_BUFFER_SIZE, | |
85 | GFP_KERNEL); | |
86 | ||
87 | if (cfs_trace_console_buffers[i][j] == NULL) | |
88 | goto out; | |
89 | } | |
90 | ||
91 | return 0; | |
92 | ||
93 | out: | |
94 | cfs_tracefile_fini_arch(); | |
95 | printk(KERN_ERR "lnet: Not enough memory\n"); | |
96 | return -ENOMEM; | |
97 | } | |
98 | ||
7d46a21a | 99 | void cfs_tracefile_fini_arch(void) |
d7e09d03 PT |
100 | { |
101 | int i; | |
102 | int j; | |
103 | ||
104 | for (i = 0; i < num_possible_cpus(); i++) | |
105 | for (j = 0; j < 3; j++) | |
106 | if (cfs_trace_console_buffers[i][j] != NULL) { | |
107 | kfree(cfs_trace_console_buffers[i][j]); | |
108 | cfs_trace_console_buffers[i][j] = NULL; | |
109 | } | |
110 | ||
111 | for (i = 0; cfs_trace_data[i] != NULL; i++) { | |
112 | kfree(cfs_trace_data[i]); | |
113 | cfs_trace_data[i] = NULL; | |
114 | } | |
115 | ||
116 | fini_rwsem(&cfs_tracefile_sem); | |
117 | } | |
118 | ||
7d46a21a | 119 | void cfs_tracefile_read_lock(void) |
d7e09d03 PT |
120 | { |
121 | down_read(&cfs_tracefile_sem); | |
122 | } | |
123 | ||
7d46a21a | 124 | void cfs_tracefile_read_unlock(void) |
d7e09d03 PT |
125 | { |
126 | up_read(&cfs_tracefile_sem); | |
127 | } | |
128 | ||
7d46a21a | 129 | void cfs_tracefile_write_lock(void) |
d7e09d03 PT |
130 | { |
131 | down_write(&cfs_tracefile_sem); | |
132 | } | |
133 | ||
7d46a21a | 134 | void cfs_tracefile_write_unlock(void) |
d7e09d03 PT |
135 | { |
136 | up_write(&cfs_tracefile_sem); | |
137 | } | |
138 | ||
7d46a21a | 139 | cfs_trace_buf_type_t cfs_trace_buf_idx_get(void) |
d7e09d03 PT |
140 | { |
141 | if (in_irq()) | |
142 | return CFS_TCD_TYPE_IRQ; | |
143 | else if (in_softirq()) | |
144 | return CFS_TCD_TYPE_SOFTIRQ; | |
145 | else | |
146 | return CFS_TCD_TYPE_PROC; | |
147 | } | |
148 | ||
149 | /* | |
150 | * The walking argument indicates the locking comes from all tcd types | |
151 | * iterator and we must lock it and dissable local irqs to avoid deadlocks | |
152 | * with other interrupt locks that might be happening. See LU-1311 | |
153 | * for details. | |
154 | */ | |
155 | int cfs_trace_lock_tcd(struct cfs_trace_cpu_data *tcd, int walking) | |
156 | { | |
157 | __LASSERT(tcd->tcd_type < CFS_TCD_TYPE_MAX); | |
158 | if (tcd->tcd_type == CFS_TCD_TYPE_IRQ) | |
159 | spin_lock_irqsave(&tcd->tcd_lock, tcd->tcd_lock_flags); | |
160 | else if (tcd->tcd_type == CFS_TCD_TYPE_SOFTIRQ) | |
161 | spin_lock_bh(&tcd->tcd_lock); | |
162 | else if (unlikely(walking)) | |
163 | spin_lock_irq(&tcd->tcd_lock); | |
164 | else | |
165 | spin_lock(&tcd->tcd_lock); | |
166 | return 1; | |
167 | } | |
168 | ||
169 | void cfs_trace_unlock_tcd(struct cfs_trace_cpu_data *tcd, int walking) | |
170 | { | |
171 | __LASSERT(tcd->tcd_type < CFS_TCD_TYPE_MAX); | |
172 | if (tcd->tcd_type == CFS_TCD_TYPE_IRQ) | |
173 | spin_unlock_irqrestore(&tcd->tcd_lock, tcd->tcd_lock_flags); | |
174 | else if (tcd->tcd_type == CFS_TCD_TYPE_SOFTIRQ) | |
175 | spin_unlock_bh(&tcd->tcd_lock); | |
176 | else if (unlikely(walking)) | |
177 | spin_unlock_irq(&tcd->tcd_lock); | |
178 | else | |
179 | spin_unlock(&tcd->tcd_lock); | |
180 | } | |
181 | ||
182 | int cfs_tcd_owns_tage(struct cfs_trace_cpu_data *tcd, | |
183 | struct cfs_trace_page *tage) | |
184 | { | |
185 | /* | |
186 | * XXX nikita: do NOT call portals_debug_msg() (CDEBUG/ENTRY/EXIT) | |
187 | * from here: this will lead to infinite recursion. | |
188 | */ | |
189 | return tcd->tcd_cpu == tage->cpu; | |
190 | } | |
191 | ||
192 | void | |
193 | cfs_set_ptldebug_header(struct ptldebug_header *header, | |
194 | struct libcfs_debug_msg_data *msgdata, | |
195 | unsigned long stack) | |
196 | { | |
197 | struct timeval tv; | |
198 | ||
199 | do_gettimeofday(&tv); | |
200 | ||
201 | header->ph_subsys = msgdata->msg_subsys; | |
202 | header->ph_mask = msgdata->msg_mask; | |
203 | header->ph_cpu_id = smp_processor_id(); | |
204 | header->ph_type = cfs_trace_buf_idx_get(); | |
205 | header->ph_sec = (__u32)tv.tv_sec; | |
206 | header->ph_usec = tv.tv_usec; | |
207 | header->ph_stack = stack; | |
208 | header->ph_pid = current->pid; | |
209 | header->ph_line_num = msgdata->msg_line; | |
210 | header->ph_extern_pid = 0; | |
211 | return; | |
212 | } | |
213 | ||
214 | static char * | |
215 | dbghdr_to_err_string(struct ptldebug_header *hdr) | |
216 | { | |
217 | switch (hdr->ph_subsys) { | |
218 | ||
219 | case S_LND: | |
220 | case S_LNET: | |
221 | return "LNetError"; | |
222 | default: | |
223 | return "LustreError"; | |
224 | } | |
225 | } | |
226 | ||
227 | static char * | |
228 | dbghdr_to_info_string(struct ptldebug_header *hdr) | |
229 | { | |
230 | switch (hdr->ph_subsys) { | |
231 | ||
232 | case S_LND: | |
233 | case S_LNET: | |
234 | return "LNet"; | |
235 | default: | |
236 | return "Lustre"; | |
237 | } | |
238 | } | |
239 | ||
240 | void cfs_print_to_console(struct ptldebug_header *hdr, int mask, | |
241 | const char *buf, int len, const char *file, | |
242 | const char *fn) | |
243 | { | |
244 | char *prefix = "Lustre", *ptype = NULL; | |
245 | ||
246 | if ((mask & D_EMERG) != 0) { | |
247 | prefix = dbghdr_to_err_string(hdr); | |
248 | ptype = KERN_EMERG; | |
249 | } else if ((mask & D_ERROR) != 0) { | |
250 | prefix = dbghdr_to_err_string(hdr); | |
251 | ptype = KERN_ERR; | |
252 | } else if ((mask & D_WARNING) != 0) { | |
253 | prefix = dbghdr_to_info_string(hdr); | |
254 | ptype = KERN_WARNING; | |
255 | } else if ((mask & (D_CONSOLE | libcfs_printk)) != 0) { | |
256 | prefix = dbghdr_to_info_string(hdr); | |
257 | ptype = KERN_INFO; | |
258 | } | |
259 | ||
260 | if ((mask & D_CONSOLE) != 0) { | |
261 | printk("%s%s: %.*s", ptype, prefix, len, buf); | |
262 | } else { | |
263 | printk("%s%s: %d:%d:(%s:%d:%s()) %.*s", ptype, prefix, | |
264 | hdr->ph_pid, hdr->ph_extern_pid, file, hdr->ph_line_num, | |
265 | fn, len, buf); | |
266 | } | |
267 | return; | |
268 | } | |
269 | ||
270 | int cfs_trace_max_debug_mb(void) | |
271 | { | |
4f6cc9ab | 272 | int total_mb = (totalram_pages >> (20 - PAGE_SHIFT)); |
d7e09d03 PT |
273 | |
274 | return MAX(512, (total_mb * 80)/100); | |
275 | } |