]> git.proxmox.com Git - mirror_spl-debian.git/blob - modules/spl/spl-generic.c
- Remapped ldi_handle_t to struct block_device * which is much more useful
[mirror_spl-debian.git] / modules / spl / spl-generic.c
1 #include <sys/sysmacros.h>
2 #include <sys/vmsystm.h>
3 #include <sys/vnode.h>
4 #include <sys/kmem.h>
5 #include <sys/debug.h>
6 #include <linux/proc_fs.h>
7 #include "config.h"
8
9 /*
10 * Generic support
11 */
12 static char spl_debug_buffer[MAXMSGLEN];
13 static spinlock_t spl_debug_lock = SPIN_LOCK_UNLOCKED;
14
15 unsigned long spl_debug_mask = 0;
16 unsigned long spl_debug_subsys = 0xff;
17 EXPORT_SYMBOL(spl_debug_mask);
18 EXPORT_SYMBOL(spl_debug_subsys);
19
20 static struct proc_dir_entry *spl_proc_root = NULL;
21 static struct proc_dir_entry *spl_proc_debug_mask = NULL;
22 static struct proc_dir_entry *spl_proc_debug_subsys = NULL;
23
24 int p0 = 0;
25 EXPORT_SYMBOL(p0);
26
27 char hw_serial[11];
28 EXPORT_SYMBOL(hw_serial);
29
30 vmem_t *zio_alloc_arena = NULL;
31 EXPORT_SYMBOL(zio_alloc_arena);
32
33
34 int
35 highbit(unsigned long i)
36 {
37 register int h = 1;
38
39 if (i == 0)
40 return (0);
41 #if BITS_PER_LONG == 64
42 if (i & 0xffffffff00000000ul) {
43 h += 32; i >>= 32;
44 }
45 #endif
46 if (i & 0xffff0000) {
47 h += 16; i >>= 16;
48 }
49 if (i & 0xff00) {
50 h += 8; i >>= 8;
51 }
52 if (i & 0xf0) {
53 h += 4; i >>= 4;
54 }
55 if (i & 0xc) {
56 h += 2; i >>= 2;
57 }
58 if (i & 0x2) {
59 h += 1;
60 }
61 return (h);
62 }
63 EXPORT_SYMBOL(highbit);
64
65 int
66 ddi_strtoul(const char *str, char **nptr, int base, unsigned long *result)
67 {
68 char *end;
69 return (*result = simple_strtoul(str, &end, base));
70 }
71 EXPORT_SYMBOL(ddi_strtoul);
72
73 /* XXX: Not the most efficient debug function ever. This should be re-done
74 * as an internal per-cpu in-memory debug log accessable via /proc/. Not as
75 * a shared global buffer everything gets serialize though. That said I'll
76 * worry about performance considerations once I've dealt with correctness.
77 */
78 void
79 __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
80 {
81 char *sfp, *start, *ptr;
82 struct timeval tv;
83 unsigned long flags;
84 va_list ap;
85
86 start = ptr = spl_debug_buffer;
87 sfp = strrchr(file, '/');
88 do_gettimeofday(&tv);
89
90 /* XXX: This is particularly bad for performance, but we need to
91 * disable irqs here or two __dprintf()'s may deadlock on each
92 * other if one if called from an irq handler. This is yet another
93 * reason why we really, really, need an internal debug log.
94 */
95 spin_lock_irqsave(&spl_debug_lock, flags);
96 ptr += snprintf(ptr, MAXMSGLEN - 1,
97 "spl: %lu.%06lu:%d:%u:%s:%d:%s(): ",
98 tv.tv_sec, tv.tv_usec, current->pid,
99 smp_processor_id(),
100 sfp == NULL ? file : sfp + 1,
101 line, func);
102
103 va_start(ap, fmt);
104 ptr += vsnprintf(ptr, MAXMSGLEN - (ptr - start) - 1, fmt, ap);
105 va_end(ap);
106
107 printk("%s", start);
108 spin_unlock_irqrestore(&spl_debug_lock, flags);
109 }
110 EXPORT_SYMBOL(__dprintf);
111
112 static int
113 spl_proc_rd_generic_ul(char *page, char **start, off_t off,
114 int count, int *eof, unsigned long val)
115 {
116 int rc;
117
118 *start = page;
119 *eof = 1;
120
121 if (off || count > PAGE_SIZE)
122 return 0;
123
124 spin_lock(&spl_debug_lock);
125 rc = snprintf(page, PAGE_SIZE, "0x%lx\n", val);
126 spin_unlock(&spl_debug_lock);
127
128 return rc;
129 }
130
131 static int
132 spl_proc_rd_debug_mask(char *page, char **start, off_t off,
133 int count, int *eof, void *data)
134 {
135 return spl_proc_rd_generic_ul(page, start, off, count,
136 eof, spl_debug_mask);
137 }
138
139 static int
140 spl_proc_rd_debug_subsys(char *page, char **start, off_t off,
141 int count, int *eof, void *data)
142 {
143 return spl_proc_rd_generic_ul(page, start, off, count,
144 eof, spl_debug_subsys);
145 }
146
147 static int
148 spl_proc_wr_generic_ul(const char *ubuf, unsigned long count,
149 unsigned long *val, int base)
150 {
151 char *end, kbuf[32];
152
153 if (count >= sizeof(kbuf))
154 return -EOVERFLOW;
155
156 if (copy_from_user(kbuf, ubuf, count))
157 return -EFAULT;
158
159 kbuf[count] = '\0';
160 *val = (int)simple_strtoul(kbuf, &end, base);
161 if (kbuf == end)
162 return -EINVAL;
163
164 return 0;
165 }
166
167 static int
168 spl_proc_wr_debug_mask(struct file *file, const char *ubuf,
169 unsigned long count, void *data, int mode)
170 {
171 unsigned long val;
172 int rc;
173
174 rc = spl_proc_wr_generic_ul(ubuf, count, &val, 16);
175 if (rc)
176 return rc;
177
178 spin_lock(&spl_debug_lock);
179 spl_debug_mask = val;
180 spin_unlock(&spl_debug_lock);
181
182 return count;
183 }
184
185 static int
186 spl_proc_wr_debug_subsys(struct file *file, const char *ubuf,
187 unsigned long count, void *data, int mode)
188 {
189 unsigned long val;
190 int rc;
191
192 rc = spl_proc_wr_generic_ul(ubuf, count, &val, 16);
193 if (rc)
194 return rc;
195
196 spin_lock(&spl_debug_lock);
197 spl_debug_subsys = val;
198 spin_unlock(&spl_debug_lock);
199
200 return count;
201 }
202
203 static struct proc_dir_entry *
204 spl_register_proc_entry(const char *name, mode_t mode,
205 struct proc_dir_entry *parent, void *data,
206 void *read_proc, void *write_proc)
207 {
208 struct proc_dir_entry *entry;
209
210 entry = create_proc_entry(name, mode, parent);
211 if (!entry)
212 return ERR_PTR(-EINVAL);
213
214 entry->data = data;
215 entry->read_proc = read_proc;
216 entry->write_proc = write_proc;
217
218 return entry;
219 } /* register_proc_entry() */
220
221 void spl_set_debug_mask(unsigned long mask) {
222 spin_lock(&spl_debug_lock);
223 spl_debug_mask = mask;
224 spin_unlock(&spl_debug_lock);
225 }
226 EXPORT_SYMBOL(spl_set_debug_mask);
227
228 void spl_set_debug_subsys(unsigned long mask) {
229 spin_lock(&spl_debug_lock);
230 spl_debug_subsys = mask;
231 spin_unlock(&spl_debug_lock);
232 }
233 EXPORT_SYMBOL(spl_set_debug_subsys);
234
235 static int __init spl_init(void)
236 {
237 int rc = 0;
238
239 spl_proc_root = proc_mkdir("spl", NULL);
240 if (!spl_proc_root) {
241 printk("spl: Error unable to create /proc/spl/ directory\n");
242 return -EINVAL;
243 }
244
245 spl_proc_debug_mask = spl_register_proc_entry("debug_mask", 0644,
246 spl_proc_root, NULL,
247 spl_proc_rd_debug_mask,
248 spl_proc_wr_debug_mask);
249 if (IS_ERR(spl_proc_debug_mask)) {
250 rc = PTR_ERR(spl_proc_debug_mask);
251 goto out;
252 }
253
254 spl_proc_debug_subsys = spl_register_proc_entry("debug_subsys", 0644,
255 spl_proc_root, NULL,
256 spl_proc_rd_debug_subsys,
257 spl_proc_wr_debug_subsys);
258 if (IS_ERR(spl_proc_debug_subsys)) {
259 rc = PTR_ERR(spl_proc_debug_subsys);
260 goto out2;
261 }
262
263 if ((rc = kmem_init()))
264 goto out2;
265
266 if ((rc = vn_init()))
267 goto out2;
268
269 strcpy(hw_serial, "007f0100"); /* loopback */
270 printk("spl: Loaded Solaris Porting Layer v%s\n", VERSION);
271
272 return 0;
273 out2:
274 if (spl_proc_debug_mask)
275 remove_proc_entry("debug_mask", spl_proc_root);
276
277 if (spl_proc_debug_subsys)
278 remove_proc_entry("debug_subsys", spl_proc_root);
279 out:
280 remove_proc_entry("spl", NULL);
281
282 return rc;
283 }
284
285 static void spl_fini(void)
286 {
287 vn_fini();
288 kmem_fini();
289
290 remove_proc_entry("debug_subsys", spl_proc_root);
291 remove_proc_entry("debug_mask", spl_proc_root);
292 remove_proc_entry("spl", NULL);
293
294 return;
295 }
296
297 module_init(spl_init);
298 module_exit(spl_fini);
299
300 MODULE_AUTHOR("Lawrence Livermore National Labs");
301 MODULE_DESCRIPTION("Solaris Porting Layer");
302 MODULE_LICENSE("GPL");