]> git.proxmox.com Git - mirror_spl-debian.git/blame - modules/spl/spl-generic.c
Adjust the condition variables to simply sleep uninteruptibly.
[mirror_spl-debian.git] / modules / spl / spl-generic.c
CommitLineData
14c5326c 1#include <sys/sysmacros.h>
af828292 2#include <sys/vmsystm.h>
3#include <sys/vnode.h>
c19c06f3 4#include <sys/kmem.h>
8d0f1ee9 5#include <sys/debug.h>
6#include <linux/proc_fs.h>
70eadc19 7#include "config.h"
f1b59d26 8
9/*
10 * Generic support
11 */
8d0f1ee9 12static char spl_debug_buffer[MAXMSGLEN];
13static spinlock_t spl_debug_lock = SPIN_LOCK_UNLOCKED;
14
15unsigned long spl_debug_mask = 0;
16unsigned long spl_debug_subsys = 0xff;
17EXPORT_SYMBOL(spl_debug_mask);
18EXPORT_SYMBOL(spl_debug_subsys);
19
20static struct proc_dir_entry *spl_proc_root = NULL;
21static struct proc_dir_entry *spl_proc_debug_mask = NULL;
22static struct proc_dir_entry *spl_proc_debug_subsys = NULL;
f1b59d26 23
24int p0 = 0;
25EXPORT_SYMBOL(p0);
70eadc19 26
2f5d55aa 27char hw_serial[11];
28EXPORT_SYMBOL(hw_serial);
29
af828292 30vmem_t *zio_alloc_arena = NULL;
31EXPORT_SYMBOL(zio_alloc_arena);
32
8d0f1ee9 33
77b1fe8f 34int
35highbit(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}
63EXPORT_SYMBOL(highbit);
64
2f5d55aa 65int
66ddi_strtoul(const char *str, char **nptr, int base, unsigned long *result)
67{
68 char *end;
69 return (*result = simple_strtoul(str, &end, base));
70}
71EXPORT_SYMBOL(ddi_strtoul);
72
8d0f1ee9 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 */
78void
79__dprintf(const char *file, const char *func, int line, const char *fmt, ...)
80{
81 char *sfp, *start, *ptr;
82 struct timeval tv;
0a6fd143 83 unsigned long flags;
8d0f1ee9 84 va_list ap;
85
86 start = ptr = spl_debug_buffer;
87 sfp = strrchr(file, '/');
88 do_gettimeofday(&tv);
89
0a6fd143 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);
8d0f1ee9 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);
0a6fd143 108 spin_unlock_irqrestore(&spl_debug_lock, flags);
8d0f1ee9 109}
110EXPORT_SYMBOL(__dprintf);
111
112static int
113spl_proc_rd_generic_ul(char *page, char **start, off_t off,
114 int count, int *eof, unsigned long val)
70eadc19 115{
af828292 116 int rc;
117
8d0f1ee9 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
131static int
132spl_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
139static int
140spl_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
147static int
148spl_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
167static int
168spl_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)
5d86345d 176 return rc;
177
8d0f1ee9 178 spin_lock(&spl_debug_lock);
179 spl_debug_mask = val;
180 spin_unlock(&spl_debug_lock);
181
182 return count;
183}
184
185static int
186spl_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)
af828292 194 return rc;
195
8d0f1ee9 196 spin_lock(&spl_debug_lock);
197 spl_debug_subsys = val;
198 spin_unlock(&spl_debug_lock);
199
200 return count;
201}
202
203static struct proc_dir_entry *
204spl_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
221void 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}
226EXPORT_SYMBOL(spl_set_debug_mask);
227
228void 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}
233EXPORT_SYMBOL(spl_set_debug_subsys);
234
235static 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
2f5d55aa 269 strcpy(hw_serial, "007f0100"); /* loopback */
8d0f1ee9 270 printk("spl: Loaded Solaris Porting Layer v%s\n", VERSION);
af828292 271
70eadc19 272 return 0;
8d0f1ee9 273out2:
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);
279out:
280 remove_proc_entry("spl", NULL);
281
282 return rc;
70eadc19 283}
284
285static void spl_fini(void)
286{
af828292 287 vn_fini();
e4f1d29f 288 kmem_fini();
c19c06f3 289
8d0f1ee9 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
70eadc19 294 return;
295}
296
297module_init(spl_init);
298module_exit(spl_fini);
299
300MODULE_AUTHOR("Lawrence Livermore National Labs");
301MODULE_DESCRIPTION("Solaris Porting Layer");
302MODULE_LICENSE("GPL");