]> git.proxmox.com Git - mirror_spl-debian.git/blob - module/spl/spl-generic.c
39357617cb973b86ee22cdae9f58ce004eba761d
[mirror_spl-debian.git] / module / spl / spl-generic.c
1 /*****************************************************************************\
2 * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
3 * Copyright (C) 2007 The Regents of the University of California.
4 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
5 * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
6 * UCRL-CODE-235197
7 *
8 * This file is part of the SPL, Solaris Porting Layer.
9 * For details, see <http://github.com/behlendorf/spl/>.
10 *
11 * The SPL is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 *
16 * The SPL is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 * for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with the SPL. If not, see <http://www.gnu.org/licenses/>.
23 *****************************************************************************
24 * Solaris Porting Layer (SPL) Generic Implementation.
25 \*****************************************************************************/
26
27 #include <sys/sysmacros.h>
28 #include <sys/systeminfo.h>
29 #include <sys/vmsystm.h>
30 #include <sys/kobj.h>
31 #include <sys/kmem.h>
32 #include <sys/mutex.h>
33 #include <sys/rwlock.h>
34 #include <sys/taskq.h>
35 #include <sys/tsd.h>
36 #include <sys/zmod.h>
37 #include <sys/debug.h>
38 #include <sys/proc.h>
39 #include <sys/kstat.h>
40 #include <sys/utsname.h>
41 #include <sys/file.h>
42 #include <linux/kmod.h>
43 #include <linux/proc_compat.h>
44 #include <spl-debug.h>
45
46 #ifdef SS_DEBUG_SUBSYS
47 #undef SS_DEBUG_SUBSYS
48 #endif
49
50 #define SS_DEBUG_SUBSYS SS_GENERIC
51
52 char spl_version[32] = "SPL v" SPL_META_VERSION "-" SPL_META_RELEASE;
53 EXPORT_SYMBOL(spl_version);
54
55 unsigned long spl_hostid = HW_INVALID_HOSTID;
56 EXPORT_SYMBOL(spl_hostid);
57 module_param(spl_hostid, ulong, 0644);
58 MODULE_PARM_DESC(spl_hostid, "The system hostid.");
59
60 char hw_serial[HW_HOSTID_LEN] = "<none>";
61 EXPORT_SYMBOL(hw_serial);
62
63 proc_t p0 = { 0 };
64 EXPORT_SYMBOL(p0);
65
66 #ifndef HAVE_KALLSYMS_LOOKUP_NAME
67 DECLARE_WAIT_QUEUE_HEAD(spl_kallsyms_lookup_name_waitq);
68 kallsyms_lookup_name_t spl_kallsyms_lookup_name_fn = SYMBOL_POISON;
69 #endif
70
71 int
72 highbit(unsigned long i)
73 {
74 register int h = 1;
75 SENTRY;
76
77 if (i == 0)
78 SRETURN(0);
79 #if BITS_PER_LONG == 64
80 if (i & 0xffffffff00000000ul) {
81 h += 32; i >>= 32;
82 }
83 #endif
84 if (i & 0xffff0000) {
85 h += 16; i >>= 16;
86 }
87 if (i & 0xff00) {
88 h += 8; i >>= 8;
89 }
90 if (i & 0xf0) {
91 h += 4; i >>= 4;
92 }
93 if (i & 0xc) {
94 h += 2; i >>= 2;
95 }
96 if (i & 0x2) {
97 h += 1;
98 }
99 SRETURN(h);
100 }
101 EXPORT_SYMBOL(highbit);
102
103 #if BITS_PER_LONG == 32
104 /*
105 * Support 64/64 => 64 division on a 32-bit platform. While the kernel
106 * provides a div64_u64() function for this we do not use it because the
107 * implementation is flawed. There are cases which return incorrect
108 * results as late as linux-2.6.35. Until this is fixed upstream the
109 * spl must provide its own implementation.
110 *
111 * This implementation is a slightly modified version of the algorithm
112 * proposed by the book 'Hacker's Delight'. The original source can be
113 * found here and is available for use without restriction.
114 *
115 * http://www.hackersdelight.org/HDcode/newCode/divDouble.c
116 */
117
118 /*
119 * Calculate number of leading of zeros for a 64-bit value.
120 */
121 static int
122 nlz64(uint64_t x) {
123 register int n = 0;
124
125 if (x == 0)
126 return 64;
127
128 if (x <= 0x00000000FFFFFFFFULL) {n = n + 32; x = x << 32;}
129 if (x <= 0x0000FFFFFFFFFFFFULL) {n = n + 16; x = x << 16;}
130 if (x <= 0x00FFFFFFFFFFFFFFULL) {n = n + 8; x = x << 8;}
131 if (x <= 0x0FFFFFFFFFFFFFFFULL) {n = n + 4; x = x << 4;}
132 if (x <= 0x3FFFFFFFFFFFFFFFULL) {n = n + 2; x = x << 2;}
133 if (x <= 0x7FFFFFFFFFFFFFFFULL) {n = n + 1;}
134
135 return n;
136 }
137
138 /*
139 * Newer kernels have a div_u64() function but we define our own
140 * to simplify portibility between kernel versions.
141 */
142 static inline uint64_t
143 __div_u64(uint64_t u, uint32_t v)
144 {
145 (void) do_div(u, v);
146 return u;
147 }
148
149 /*
150 * Implementation of 64-bit unsigned division for 32-bit machines.
151 *
152 * First the procedure takes care of the case in which the divisor is a
153 * 32-bit quantity. There are two subcases: (1) If the left half of the
154 * dividend is less than the divisor, one execution of do_div() is all that
155 * is required (overflow is not possible). (2) Otherwise it does two
156 * divisions, using the grade school method.
157 */
158 uint64_t
159 __udivdi3(uint64_t u, uint64_t v)
160 {
161 uint64_t u0, u1, v1, q0, q1, k;
162 int n;
163
164 if (v >> 32 == 0) { // If v < 2**32:
165 if (u >> 32 < v) { // If u/v cannot overflow,
166 return __div_u64(u, v); // just do one division.
167 } else { // If u/v would overflow:
168 u1 = u >> 32; // Break u into two halves.
169 u0 = u & 0xFFFFFFFF;
170 q1 = __div_u64(u1, v); // First quotient digit.
171 k = u1 - q1 * v; // First remainder, < v.
172 u0 += (k << 32);
173 q0 = __div_u64(u0, v); // Seconds quotient digit.
174 return (q1 << 32) + q0;
175 }
176 } else { // If v >= 2**32:
177 n = nlz64(v); // 0 <= n <= 31.
178 v1 = (v << n) >> 32; // Normalize divisor, MSB is 1.
179 u1 = u >> 1; // To ensure no overflow.
180 q1 = __div_u64(u1, v1); // Get quotient from
181 q0 = (q1 << n) >> 31; // Undo normalization and
182 // division of u by 2.
183 if (q0 != 0) // Make q0 correct or
184 q0 = q0 - 1; // too small by 1.
185 if ((u - q0 * v) >= v)
186 q0 = q0 + 1; // Now q0 is correct.
187
188 return q0;
189 }
190 }
191 EXPORT_SYMBOL(__udivdi3);
192
193 /*
194 * Implementation of 64-bit signed division for 32-bit machines.
195 */
196 int64_t
197 __divdi3(int64_t u, int64_t v)
198 {
199 int64_t q, t;
200 q = __udivdi3(abs64(u), abs64(v));
201 t = (u ^ v) >> 63; // If u, v have different
202 return (q ^ t) - t; // signs, negate q.
203 }
204 EXPORT_SYMBOL(__divdi3);
205
206 /*
207 * Implementation of 64-bit unsigned modulo for 32-bit machines.
208 */
209 uint64_t
210 __umoddi3(uint64_t dividend, uint64_t divisor)
211 {
212 return (dividend - (divisor * __udivdi3(dividend, divisor)));
213 }
214 EXPORT_SYMBOL(__umoddi3);
215
216 #if defined(__arm) || defined(__arm__)
217 /*
218 * Implementation of 64-bit (un)signed division for 32-bit arm machines.
219 *
220 * Run-time ABI for the ARM Architecture (page 20). A pair of (unsigned)
221 * long longs is returned in {{r0, r1}, {r2,r3}}, the quotient in {r0, r1},
222 * and the remainder in {r2, r3}. The return type is specifically left
223 * set to 'void' to ensure the compiler does not overwrite these registers
224 * during the return. All results are in registers as per ABI
225 */
226 void
227 __aeabi_uldivmod(uint64_t u, uint64_t v)
228 {
229 uint64_t res;
230 uint64_t mod;
231
232 res = __udivdi3(u, v);
233 mod = __umoddi3(u, v);
234 {
235 register uint32_t r0 asm("r0") = (res & 0xFFFFFFFF);
236 register uint32_t r1 asm("r1") = (res >> 32);
237 register uint32_t r2 asm("r2") = (mod & 0xFFFFFFFF);
238 register uint32_t r3 asm("r3") = (mod >> 32);
239
240 asm volatile(""
241 : "+r"(r0), "+r"(r1), "+r"(r2),"+r"(r3) /* output */
242 : "r"(r0), "r"(r1), "r"(r2), "r"(r3)); /* input */
243
244 return; /* r0; */
245 }
246 }
247 EXPORT_SYMBOL(__aeabi_uldivmod);
248
249 void
250 __aeabi_ldivmod(int64_t u, int64_t v)
251 {
252 int64_t res;
253 uint64_t mod;
254
255 res = __divdi3(u, v);
256 mod = __umoddi3(u, v);
257 {
258 register uint32_t r0 asm("r0") = (res & 0xFFFFFFFF);
259 register uint32_t r1 asm("r1") = (res >> 32);
260 register uint32_t r2 asm("r2") = (mod & 0xFFFFFFFF);
261 register uint32_t r3 asm("r3") = (mod >> 32);
262
263 asm volatile(""
264 : "+r"(r0), "+r"(r1), "+r"(r2),"+r"(r3) /* output */
265 : "r"(r0), "r"(r1), "r"(r2), "r"(r3)); /* input */
266
267 return; /* r0; */
268 }
269 }
270 EXPORT_SYMBOL(__aeabi_ldivmod);
271 #endif /* __arm || __arm__ */
272 #endif /* BITS_PER_LONG */
273
274 /* NOTE: The strtoxx behavior is solely based on my reading of the Solaris
275 * ddi_strtol(9F) man page. I have not verified the behavior of these
276 * functions against their Solaris counterparts. It is possible that I
277 * may have misinterpreted the man page or the man page is incorrect.
278 */
279 int ddi_strtoul(const char *, char **, int, unsigned long *);
280 int ddi_strtol(const char *, char **, int, long *);
281 int ddi_strtoull(const char *, char **, int, unsigned long long *);
282 int ddi_strtoll(const char *, char **, int, long long *);
283
284 #define define_ddi_strtoux(type, valtype) \
285 int ddi_strtou##type(const char *str, char **endptr, \
286 int base, valtype *result) \
287 { \
288 valtype last_value, value = 0; \
289 char *ptr = (char *)str; \
290 int flag = 1, digit; \
291 \
292 if (strlen(ptr) == 0) \
293 return EINVAL; \
294 \
295 /* Auto-detect base based on prefix */ \
296 if (!base) { \
297 if (str[0] == '0') { \
298 if (tolower(str[1])=='x' && isxdigit(str[2])) { \
299 base = 16; /* hex */ \
300 ptr += 2; \
301 } else if (str[1] >= '0' && str[1] < 8) { \
302 base = 8; /* octal */ \
303 ptr += 1; \
304 } else { \
305 return EINVAL; \
306 } \
307 } else { \
308 base = 10; /* decimal */ \
309 } \
310 } \
311 \
312 while (1) { \
313 if (isdigit(*ptr)) \
314 digit = *ptr - '0'; \
315 else if (isalpha(*ptr)) \
316 digit = tolower(*ptr) - 'a' + 10; \
317 else \
318 break; \
319 \
320 if (digit >= base) \
321 break; \
322 \
323 last_value = value; \
324 value = value * base + digit; \
325 if (last_value > value) /* Overflow */ \
326 return ERANGE; \
327 \
328 flag = 1; \
329 ptr++; \
330 } \
331 \
332 if (flag) \
333 *result = value; \
334 \
335 if (endptr) \
336 *endptr = (char *)(flag ? ptr : str); \
337 \
338 return 0; \
339 } \
340
341 #define define_ddi_strtox(type, valtype) \
342 int ddi_strto##type(const char *str, char **endptr, \
343 int base, valtype *result) \
344 { \
345 int rc; \
346 \
347 if (*str == '-') { \
348 rc = ddi_strtou##type(str + 1, endptr, base, result); \
349 if (!rc) { \
350 if (*endptr == str + 1) \
351 *endptr = (char *)str; \
352 else \
353 *result = -*result; \
354 } \
355 } else { \
356 rc = ddi_strtou##type(str, endptr, base, result); \
357 } \
358 \
359 return rc; \
360 }
361
362 define_ddi_strtoux(l, unsigned long)
363 define_ddi_strtox(l, long)
364 define_ddi_strtoux(ll, unsigned long long)
365 define_ddi_strtox(ll, long long)
366
367 EXPORT_SYMBOL(ddi_strtoul);
368 EXPORT_SYMBOL(ddi_strtol);
369 EXPORT_SYMBOL(ddi_strtoll);
370 EXPORT_SYMBOL(ddi_strtoull);
371
372 int
373 ddi_copyin(const void *from, void *to, size_t len, int flags)
374 {
375 /* Fake ioctl() issued by kernel, 'from' is a kernel address */
376 if (flags & FKIOCTL) {
377 memcpy(to, from, len);
378 return 0;
379 }
380
381 return copyin(from, to, len);
382 }
383 EXPORT_SYMBOL(ddi_copyin);
384
385 int
386 ddi_copyout(const void *from, void *to, size_t len, int flags)
387 {
388 /* Fake ioctl() issued by kernel, 'from' is a kernel address */
389 if (flags & FKIOCTL) {
390 memcpy(to, from, len);
391 return 0;
392 }
393
394 return copyout(from, to, len);
395 }
396 EXPORT_SYMBOL(ddi_copyout);
397
398 #ifndef HAVE_PUT_TASK_STRUCT
399 /*
400 * This is only a stub function which should never be used. The SPL should
401 * never be putting away the last reference on a task structure so this will
402 * not be called. However, we still need to define it so the module does not
403 * have undefined symbol at load time. That all said if this impossible
404 * thing does somehow happen PANIC immediately so we know about it.
405 */
406 void
407 __put_task_struct(struct task_struct *t)
408 {
409 PANIC("Unexpectly put last reference on task %d\n", (int)t->pid);
410 }
411 EXPORT_SYMBOL(__put_task_struct);
412 #endif /* HAVE_PUT_TASK_STRUCT */
413
414 struct new_utsname *__utsname(void)
415 {
416 #ifdef HAVE_INIT_UTSNAME
417 return init_utsname();
418 #else
419 return &system_utsname;
420 #endif
421 }
422 EXPORT_SYMBOL(__utsname);
423
424
425 /*
426 * Read the unique system identifier from the /etc/hostid file.
427 *
428 * The behavior of /usr/bin/hostid on Linux systems with the
429 * regular eglibc and coreutils is:
430 *
431 * 1. Generate the value if the /etc/hostid file does not exist
432 * or if the /etc/hostid file is less than four bytes in size.
433 *
434 * 2. If the /etc/hostid file is at least 4 bytes, then return
435 * the first four bytes [0..3] in native endian order.
436 *
437 * 3. Always ignore bytes [4..] if they exist in the file.
438 *
439 * Only the first four bytes are significant, even on systems that
440 * have a 64-bit word size.
441 *
442 * See:
443 *
444 * eglibc: sysdeps/unix/sysv/linux/gethostid.c
445 * coreutils: src/hostid.c
446 *
447 * Notes:
448 *
449 * The /etc/hostid file on Solaris is a text file that often reads:
450 *
451 * # DO NOT EDIT
452 * "0123456789"
453 *
454 * Directly copying this file to Linux results in a constant
455 * hostid of 4f442023 because the default comment constitutes
456 * the first four bytes of the file.
457 *
458 */
459
460 char *spl_hostid_path = HW_HOSTID_PATH;
461 module_param(spl_hostid_path, charp, 0444);
462 MODULE_PARM_DESC(spl_hostid_path, "The system hostid file (/etc/hostid)");
463
464 static int
465 hostid_read(void)
466 {
467 int result;
468 uint64_t size;
469 struct _buf *file;
470 unsigned long hostid = 0;
471
472 file = kobj_open_file(spl_hostid_path);
473
474 if (file == (struct _buf *)-1)
475 return -1;
476
477 result = kobj_get_filesize(file, &size);
478
479 if (result != 0) {
480 printk(KERN_WARNING
481 "SPL: kobj_get_filesize returned %i on %s\n",
482 result, spl_hostid_path);
483 kobj_close_file(file);
484 return -2;
485 }
486
487 if (size < sizeof(HW_HOSTID_MASK)) {
488 printk(KERN_WARNING
489 "SPL: Ignoring the %s file because it is %llu bytes; "
490 "expecting %lu bytes instead.\n", spl_hostid_path,
491 size, (unsigned long)sizeof(HW_HOSTID_MASK));
492 kobj_close_file(file);
493 return -3;
494 }
495
496 /* Read directly into the variable like eglibc does. */
497 /* Short reads are okay; native behavior is preserved. */
498 result = kobj_read_file(file, (char *)&hostid, sizeof(hostid), 0);
499
500 if (result < 0) {
501 printk(KERN_WARNING
502 "SPL: kobj_read_file returned %i on %s\n",
503 result, spl_hostid_path);
504 kobj_close_file(file);
505 return -4;
506 }
507
508 /* Mask down to 32 bits like coreutils does. */
509 spl_hostid = hostid & HW_HOSTID_MASK;
510 kobj_close_file(file);
511 return 0;
512 }
513
514 #define GET_HOSTID_CMD \
515 "exec 0</dev/null " \
516 " 1>/proc/sys/kernel/spl/hostid " \
517 " 2>/dev/null; " \
518 "hostid"
519
520 static int
521 hostid_exec(void)
522 {
523 char *argv[] = { "/bin/sh",
524 "-c",
525 GET_HOSTID_CMD,
526 NULL };
527 char *envp[] = { "HOME=/",
528 "TERM=linux",
529 "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
530 NULL };
531 int rc;
532
533 /* Doing address resolution in the kernel is tricky and just
534 * not a good idea in general. So to set the proper 'hw_serial'
535 * use the usermodehelper support to ask '/bin/sh' to run
536 * '/usr/bin/hostid' and redirect the result to /proc/sys/spl/hostid
537 * for us to use. It's a horrific solution but it will do for now.
538 */
539 rc = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
540 if (rc)
541 printk("SPL: Failed user helper '%s %s %s', rc = %d\n",
542 argv[0], argv[1], argv[2], rc);
543
544 return rc;
545 }
546
547 uint32_t
548 zone_get_hostid(void *zone)
549 {
550 static int first = 1;
551 unsigned long hostid;
552 int rc;
553
554 /* Only the global zone is supported */
555 ASSERT(zone == NULL);
556
557 if (first) {
558 first = 0;
559
560 /*
561 * Get the hostid if it was not passed as a module parameter.
562 * Try reading the /etc/hostid file directly, and then fall
563 * back to calling the /usr/bin/hostid utility.
564 */
565 if ((spl_hostid == HW_INVALID_HOSTID) &&
566 (rc = hostid_read()) && (rc = hostid_exec()))
567 return HW_INVALID_HOSTID;
568
569 printk(KERN_NOTICE "SPL: using hostid 0x%08x\n",
570 (unsigned int) spl_hostid);
571 }
572
573 if (ddi_strtoul(hw_serial, NULL, HW_HOSTID_LEN-1, &hostid) != 0)
574 return HW_INVALID_HOSTID;
575
576 return (uint32_t)hostid;
577 }
578 EXPORT_SYMBOL(zone_get_hostid);
579
580 #ifndef HAVE_KALLSYMS_LOOKUP_NAME
581 /*
582 * The kallsyms_lookup_name() kernel function is not an exported symbol in
583 * Linux 2.6.19 through 2.6.32 inclusive.
584 *
585 * This function replaces the functionality by performing an upcall to user
586 * space where /proc/kallsyms is consulted for the requested address.
587 *
588 */
589
590 #define GET_KALLSYMS_ADDR_CMD \
591 "exec 0</dev/null " \
592 " 1>/proc/sys/kernel/spl/kallsyms_lookup_name " \
593 " 2>/dev/null; " \
594 "awk '{ if ( $3 == \"kallsyms_lookup_name\" ) { print $1 } }' " \
595 " /proc/kallsyms "
596
597 static int
598 set_kallsyms_lookup_name(void)
599 {
600 char *argv[] = { "/bin/sh",
601 "-c",
602 GET_KALLSYMS_ADDR_CMD,
603 NULL };
604 char *envp[] = { "HOME=/",
605 "TERM=linux",
606 "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
607 NULL };
608 int rc;
609
610 rc = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
611
612 /*
613 * Due to I/O buffering the helper may return successfully before
614 * the proc handler has a chance to execute. To catch this case
615 * wait up to 1 second to verify spl_kallsyms_lookup_name_fn was
616 * updated to a non SYMBOL_POISON value.
617 */
618 if (rc == 0) {
619 rc = wait_event_timeout(spl_kallsyms_lookup_name_waitq,
620 spl_kallsyms_lookup_name_fn != SYMBOL_POISON, HZ);
621 if (rc == 0)
622 rc = -ETIMEDOUT;
623 else if (spl_kallsyms_lookup_name_fn == SYMBOL_POISON)
624 rc = -EFAULT;
625 else
626 rc = 0;
627 }
628
629 if (rc)
630 printk("SPL: Failed user helper '%s %s %s', rc = %d\n",
631 argv[0], argv[1], argv[2], rc);
632
633 return rc;
634 }
635 #endif
636
637 static int
638 __init spl_init(void)
639 {
640 int rc = 0;
641
642 if ((rc = spl_debug_init()))
643 return rc;
644
645 if ((rc = spl_kmem_init()))
646 SGOTO(out1, rc);
647
648 if ((rc = spl_mutex_init()))
649 SGOTO(out2, rc);
650
651 if ((rc = spl_rw_init()))
652 SGOTO(out3, rc);
653
654 if ((rc = spl_taskq_init()))
655 SGOTO(out4, rc);
656
657 if ((rc = spl_vn_init()))
658 SGOTO(out5, rc);
659
660 if ((rc = spl_proc_init()))
661 SGOTO(out6, rc);
662
663 if ((rc = spl_kstat_init()))
664 SGOTO(out7, rc);
665
666 if ((rc = spl_tsd_init()))
667 SGOTO(out8, rc);
668
669 if ((rc = spl_zlib_init()))
670 SGOTO(out9, rc);
671
672 #ifndef HAVE_KALLSYMS_LOOKUP_NAME
673 if ((rc = set_kallsyms_lookup_name()))
674 SGOTO(out10, rc = -EADDRNOTAVAIL);
675 #endif /* HAVE_KALLSYMS_LOOKUP_NAME */
676
677 if ((rc = spl_kmem_init_kallsyms_lookup()))
678 SGOTO(out10, rc);
679
680 if ((rc = spl_vn_init_kallsyms_lookup()))
681 SGOTO(out10, rc);
682
683 printk(KERN_NOTICE "SPL: Loaded module v%s-%s%s\n", SPL_META_VERSION,
684 SPL_META_RELEASE, SPL_DEBUG_STR);
685 SRETURN(rc);
686 out10:
687 spl_zlib_fini();
688 out9:
689 spl_tsd_fini();
690 out8:
691 spl_kstat_fini();
692 out7:
693 spl_proc_fini();
694 out6:
695 spl_vn_fini();
696 out5:
697 spl_taskq_fini();
698 out4:
699 spl_rw_fini();
700 out3:
701 spl_mutex_fini();
702 out2:
703 spl_kmem_fini();
704 out1:
705 spl_debug_fini();
706
707 printk(KERN_NOTICE "SPL: Failed to Load Solaris Porting Layer "
708 "v%s-%s%s, rc = %d\n", SPL_META_VERSION, SPL_META_RELEASE,
709 SPL_DEBUG_STR, rc);
710 return rc;
711 }
712
713 static void
714 spl_fini(void)
715 {
716 SENTRY;
717
718 printk(KERN_NOTICE "SPL: Unloaded module v%s-%s%s\n",
719 SPL_META_VERSION, SPL_META_RELEASE, SPL_DEBUG_STR);
720 spl_zlib_fini();
721 spl_tsd_fini();
722 spl_kstat_fini();
723 spl_proc_fini();
724 spl_vn_fini();
725 spl_taskq_fini();
726 spl_rw_fini();
727 spl_mutex_fini();
728 spl_kmem_fini();
729 spl_debug_fini();
730 }
731
732 /* Called when a dependent module is loaded */
733 void
734 spl_setup(void)
735 {
736 int rc;
737
738 /*
739 * At module load time the pwd is set to '/' on a Solaris system.
740 * On a Linux system will be set to whatever directory the caller
741 * was in when executing insmod/modprobe.
742 */
743 rc = vn_set_pwd("/");
744 if (rc)
745 printk("SPL: Warning unable to set pwd to '/': %d\n", rc);
746 }
747 EXPORT_SYMBOL(spl_setup);
748
749 /* Called when a dependent module is unloaded */
750 void
751 spl_cleanup(void)
752 {
753 }
754 EXPORT_SYMBOL(spl_cleanup);
755
756 module_init(spl_init);
757 module_exit(spl_fini);
758
759 MODULE_AUTHOR("Lawrence Livermore National Labs");
760 MODULE_DESCRIPTION("Solaris Porting Layer");
761 MODULE_LICENSE("GPL");