Whamcloud - gitweb
LU-8403 obd: remove OBD_NOTIFY_SYNC{,_NONBLOCK}
[fs/lustre-release.git] / libcfs / libcfs / module.c
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.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2012, 2015, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  * Lustre is a trademark of Sun Microsystems, Inc.
31  */
32 #include <linux/module.h>
33 #include <linux/kernel.h>
34 #include <linux/mm.h>
35 #include <linux/string.h>
36 #include <linux/stat.h>
37 #include <linux/errno.h>
38 #include <linux/unistd.h>
39 #include <net/sock.h>
40 #include <linux/uio.h>
41 #include <linux/uaccess.h>
42
43 #include <linux/fs.h>
44 #include <linux/file.h>
45 #include <linux/list.h>
46
47 #include <linux/sysctl.h>
48 #include <linux/proc_fs.h>
49 #include <asm/div64.h>
50
51 #define DEBUG_SUBSYSTEM S_LNET
52
53 #include <libcfs/libcfs.h>
54 #include <libcfs/libcfs_crypto.h>
55 #include <lnet/lib-lnet.h>
56 #include "tracefile.h"
57
58 #ifdef CONFIG_SYSCTL
59 static struct ctl_table_header *lnet_table_header;
60 #endif
61
62 static DECLARE_RWSEM(ioctl_list_sem);
63 static LIST_HEAD(ioctl_list);
64
65 int libcfs_register_ioctl(struct libcfs_ioctl_handler *hand)
66 {
67         int rc = 0;
68
69         down_write(&ioctl_list_sem);
70         if (!list_empty(&hand->item))
71                 rc = -EBUSY;
72         else
73                 list_add_tail(&hand->item, &ioctl_list);
74         up_write(&ioctl_list_sem);
75
76         return rc;
77 }
78 EXPORT_SYMBOL(libcfs_register_ioctl);
79
80 int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand)
81 {
82         int rc = 0;
83
84         down_write(&ioctl_list_sem);
85         if (list_empty(&hand->item))
86                 rc = -ENOENT;
87         else
88                 list_del_init(&hand->item);
89         up_write(&ioctl_list_sem);
90
91         return rc;
92 }
93 EXPORT_SYMBOL(libcfs_deregister_ioctl);
94
95 int libcfs_ioctl(unsigned long cmd, void __user *uparam)
96 {
97         struct libcfs_ioctl_data *data = NULL;
98         struct libcfs_ioctl_hdr  *hdr;
99         int                       err;
100         ENTRY;
101
102         /* 'cmd' and permissions get checked in our arch-specific caller */
103         err = libcfs_ioctl_getdata(&hdr, uparam);
104         if (err != 0) {
105                 CDEBUG_LIMIT(D_ERROR,
106                              "libcfs ioctl: data header error %d\n", err);
107                 RETURN(err);
108         }
109
110         if (hdr->ioc_version == LIBCFS_IOCTL_VERSION) {
111                 /* The libcfs_ioctl_data_adjust() function performs adjustment
112                  * operations on the libcfs_ioctl_data structure to make
113                  * it usable by the code.  This doesn't need to be called
114                  * for new data structures added. */
115                 data = container_of(hdr, struct libcfs_ioctl_data, ioc_hdr);
116                 err = libcfs_ioctl_data_adjust(data);
117                 if (err != 0)
118                         GOTO(out, err);
119         }
120
121         CDEBUG(D_IOCTL, "libcfs ioctl cmd %lu\n", cmd);
122         switch (cmd) {
123         case IOC_LIBCFS_CLEAR_DEBUG:
124                 libcfs_debug_clear_buffer();
125                 break;
126         case IOC_LIBCFS_MARK_DEBUG:
127                 if (data == NULL ||
128                     data->ioc_inlbuf1 == NULL ||
129                     data->ioc_inlbuf1[data->ioc_inllen1 - 1] != '\0')
130                         GOTO(out, err = -EINVAL);
131
132                 libcfs_debug_mark_buffer(data->ioc_inlbuf1);
133                 break;
134
135         default: {
136                 struct libcfs_ioctl_handler *hand;
137
138                 err = -EINVAL;
139                 down_read(&ioctl_list_sem);
140                 list_for_each_entry(hand, &ioctl_list, item) {
141                         err = hand->handle_ioctl(cmd, hdr);
142                         if (err == -EINVAL)
143                                 continue;
144
145                         if (err == 0) {
146                                 if (copy_to_user(uparam, hdr, hdr->ioc_len))
147                                         err = -EFAULT;
148                         }
149                         break;
150                 }
151                 up_read(&ioctl_list_sem);
152                 break; }
153         }
154 out:
155         LIBCFS_FREE(hdr, hdr->ioc_len);
156         RETURN(err);
157 }
158
159 int
160 lprocfs_call_handler(void *data, int write, loff_t *ppos,
161                      void __user *buffer, size_t *lenp,
162                      int (*handler)(void *data, int write, loff_t pos,
163                                     void __user *buffer, int len))
164 {
165         int rc = handler(data, write, *ppos, buffer, *lenp);
166
167         if (rc < 0)
168                 return rc;
169
170         if (write) {
171                 *ppos += *lenp;
172         } else {
173                 *lenp = rc;
174                 *ppos += rc;
175         }
176         return 0;
177 }
178 EXPORT_SYMBOL(lprocfs_call_handler);
179
180 static int __proc_dobitmasks(void *data, int write,
181                              loff_t pos, void __user *buffer, int nob)
182 {
183         const int     tmpstrlen = 512;
184         char         *tmpstr;
185         int           rc;
186         unsigned int *mask = data;
187         int           is_subsys = (mask == &libcfs_subsystem_debug) ? 1 : 0;
188         int           is_printk = (mask == &libcfs_printk) ? 1 : 0;
189
190         rc = cfs_trace_allocate_string_buffer(&tmpstr, tmpstrlen);
191         if (rc < 0)
192                 return rc;
193
194         if (!write) {
195                 libcfs_debug_mask2str(tmpstr, tmpstrlen, *mask, is_subsys);
196                 rc = strlen(tmpstr);
197
198                 if (pos >= rc) {
199                         rc = 0;
200                 } else {
201                         rc = cfs_trace_copyout_string(buffer, nob,
202                                                       tmpstr + pos, "\n");
203                 }
204         } else {
205                 rc = cfs_trace_copyin_string(tmpstr, tmpstrlen, buffer, nob);
206                 if (rc < 0) {
207                         kfree(tmpstr);
208                         return rc;
209                 }
210
211                 rc = libcfs_debug_str2mask(mask, tmpstr, is_subsys);
212                 /* Always print LBUG/LASSERT to console, so keep this mask */
213                 if (is_printk)
214                         *mask |= D_EMERG;
215         }
216
217         kfree(tmpstr);
218         return rc;
219 }
220
221 static int
222 proc_dobitmasks(struct ctl_table *table, int write,
223                 void __user *buffer, size_t *lenp, loff_t *ppos)
224 {
225         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
226                                     __proc_dobitmasks);
227 }
228
229 static int min_watchdog_ratelimit;              /* disable ratelimiting */
230 static int max_watchdog_ratelimit = (24*60*60); /* limit to once per day */
231
232 static int __proc_dump_kernel(void *data, int write,
233                               loff_t pos, void __user *buffer, int nob)
234 {
235         if (!write)
236                 return 0;
237
238         return cfs_trace_dump_debug_buffer_usrstr(buffer, nob);
239 }
240
241 static int
242 proc_dump_kernel(struct ctl_table *table, int write, void __user *buffer,
243                  size_t *lenp, loff_t *ppos)
244 {
245         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
246                                     __proc_dump_kernel);
247 }
248
249 static int __proc_daemon_file(void *data, int write,
250                               loff_t pos, void __user *buffer, int nob)
251 {
252         if (!write) {
253                 int len = strlen(cfs_tracefile);
254
255                 if (pos >= len)
256                         return 0;
257
258                 return cfs_trace_copyout_string(buffer, nob,
259                                                 cfs_tracefile + pos, "\n");
260         }
261
262         return cfs_trace_daemon_command_usrstr(buffer, nob);
263 }
264
265 static int
266 proc_daemon_file(struct ctl_table *table, int write, void __user *buffer,
267                  size_t *lenp, loff_t *ppos)
268 {
269         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
270                                     __proc_daemon_file);
271 }
272
273 static int __proc_debug_mb(void *data, int write,
274                            loff_t pos, void __user *buffer, int nob)
275 {
276         if (!write) {
277                 char tmpstr[32];
278                 int  len = snprintf(tmpstr, sizeof(tmpstr), "%d",
279                                     cfs_trace_get_debug_mb());
280
281                 if (pos >= len)
282                         return 0;
283
284                 return cfs_trace_copyout_string(buffer, nob, tmpstr + pos,
285                                                 "\n");
286         }
287
288         return cfs_trace_set_debug_mb_usrstr(buffer, nob);
289 }
290
291 static int
292 proc_debug_mb(struct ctl_table *table, int write, void __user *buffer,
293               size_t *lenp, loff_t *ppos)
294 {
295         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
296                                     __proc_debug_mb);
297 }
298
299 static int
300 proc_console_max_delay_cs(struct ctl_table *table, int write,
301                           void __user *buffer, size_t *lenp, loff_t *ppos)
302 {
303         int rc, max_delay_cs;
304         struct ctl_table dummy = *table;
305         cfs_duration_t d;
306
307         dummy.data = &max_delay_cs;
308         dummy.proc_handler = &proc_dointvec;
309
310         if (!write) { /* read */
311                 max_delay_cs = cfs_duration_sec(libcfs_console_max_delay * 100);
312                 rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
313                 return rc;
314         }
315
316         /* write */
317         max_delay_cs = 0;
318         rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
319         if (rc < 0)
320                 return rc;
321         if (max_delay_cs <= 0)
322                 return -EINVAL;
323
324         d = cfs_time_seconds(max_delay_cs) / 100;
325         if (d == 0 || d < libcfs_console_min_delay)
326                 return -EINVAL;
327         libcfs_console_max_delay = d;
328
329         return rc;
330 }
331
332 static int
333 proc_console_min_delay_cs(struct ctl_table *table, int write,
334                           void __user *buffer, size_t *lenp, loff_t *ppos)
335 {
336         int rc, min_delay_cs;
337         struct ctl_table dummy = *table;
338         cfs_duration_t d;
339
340         dummy.data = &min_delay_cs;
341         dummy.proc_handler = &proc_dointvec;
342
343         if (!write) { /* read */
344                 min_delay_cs = cfs_duration_sec(libcfs_console_min_delay * 100);
345                 rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
346                 return rc;
347         }
348
349         /* write */
350         min_delay_cs = 0;
351         rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
352         if (rc < 0)
353                 return rc;
354         if (min_delay_cs <= 0)
355                 return -EINVAL;
356
357         d = cfs_time_seconds(min_delay_cs) / 100;
358         if (d == 0 || d > libcfs_console_max_delay)
359                 return -EINVAL;
360         libcfs_console_min_delay = d;
361
362         return rc;
363 }
364
365 static int
366 proc_console_backoff(struct ctl_table *table, int write, void __user *buffer,
367                      size_t *lenp, loff_t *ppos)
368 {
369         int rc, backoff;
370         struct ctl_table dummy = *table;
371
372         dummy.data = &backoff;
373         dummy.proc_handler = &proc_dointvec;
374
375         if (!write) { /* read */
376                 backoff = libcfs_console_backoff;
377                 rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
378                 return rc;
379         }
380
381         /* write */
382         backoff = 0;
383         rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
384         if (rc < 0)
385                 return rc;
386
387         if (backoff <= 0)
388                 return -EINVAL;
389
390         libcfs_console_backoff = backoff;
391
392         return rc;
393 }
394
395 static int
396 libcfs_force_lbug(struct ctl_table *table, int write, void __user *buffer,
397                   size_t *lenp, loff_t *ppos)
398 {
399         if (write)
400                 LBUG();
401         return 0;
402 }
403
404 static int
405 proc_fail_loc(struct ctl_table *table, int write, void __user *buffer,
406               size_t *lenp, loff_t *ppos)
407 {
408         int rc;
409         long old_fail_loc = cfs_fail_loc;
410
411         rc = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
412         if (old_fail_loc != cfs_fail_loc)
413                 wake_up(&cfs_race_waitq);
414         return rc;
415 }
416
417 static int __proc_cpt_table(void *data, int write,
418                             loff_t pos, void __user *buffer, int nob)
419 {
420         char *buf = NULL;
421         int   len = 4096;
422         int   rc  = 0;
423
424         if (write)
425                 return -EPERM;
426
427         LASSERT(cfs_cpt_table != NULL);
428
429         while (1) {
430                 LIBCFS_ALLOC(buf, len);
431                 if (buf == NULL)
432                         return -ENOMEM;
433
434                 rc = cfs_cpt_table_print(cfs_cpt_table, buf, len);
435                 if (rc >= 0)
436                         break;
437
438                 if (rc == -EFBIG) {
439                         LIBCFS_FREE(buf, len);
440                         len <<= 1;
441                         continue;
442                 }
443                 goto out;
444         }
445
446         if (pos >= rc) {
447                 rc = 0;
448                 goto out;
449         }
450
451         rc = cfs_trace_copyout_string(buffer, nob, buf + pos, NULL);
452 out:
453         if (buf != NULL)
454                 LIBCFS_FREE(buf, len);
455         return rc;
456 }
457
458 static int
459 proc_cpt_table(struct ctl_table *table, int write, void __user *buffer,
460                size_t *lenp, loff_t *ppos)
461 {
462         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
463                                     __proc_cpt_table);
464 }
465
466 static int __proc_cpt_distance(void *data, int write,
467                                loff_t pos, void __user *buffer, int nob)
468 {
469         char *buf = NULL;
470         int   len = 4096;
471         int   rc  = 0;
472
473         if (write)
474                 return -EPERM;
475
476         LASSERT(cfs_cpt_table != NULL);
477
478         while (1) {
479                 LIBCFS_ALLOC(buf, len);
480                 if (buf == NULL)
481                         return -ENOMEM;
482
483                 rc = cfs_cpt_distance_print(cfs_cpt_table, buf, len);
484                 if (rc >= 0)
485                         break;
486
487                 if (rc == -EFBIG) {
488                         LIBCFS_FREE(buf, len);
489                         len <<= 1;
490                         continue;
491                 }
492                 goto out;
493         }
494
495         if (pos >= rc) {
496                 rc = 0;
497                 goto out;
498         }
499
500         rc = cfs_trace_copyout_string(buffer, nob, buf + pos, NULL);
501  out:
502         if (buf != NULL)
503                 LIBCFS_FREE(buf, len);
504         return rc;
505 }
506
507 static int
508 proc_cpt_distance(struct ctl_table *table, int write, void __user *buffer,
509                size_t *lenp, loff_t *ppos)
510 {
511         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
512                                      __proc_cpt_distance);
513 }
514
515 static struct ctl_table lnet_table[] = {
516         /*
517          * NB No .strategy entries have been provided since sysctl(8) prefers
518          * to go via /proc for portability.
519          */
520         {
521                 INIT_CTL_NAME
522                 .procname       = "debug",
523                 .data           = &libcfs_debug,
524                 .maxlen         = sizeof(int),
525                 .mode           = 0644,
526                 .proc_handler   = &proc_dobitmasks,
527         },
528         {
529                 INIT_CTL_NAME
530                 .procname       = "subsystem_debug",
531                 .data           = &libcfs_subsystem_debug,
532                 .maxlen         = sizeof(int),
533                 .mode           = 0644,
534                 .proc_handler   = &proc_dobitmasks,
535         },
536         {
537                 INIT_CTL_NAME
538                 .procname       = "printk",
539                 .data           = &libcfs_printk,
540                 .maxlen         = sizeof(int),
541                 .mode           = 0644,
542                 .proc_handler   = &proc_dobitmasks,
543         },
544         {
545                 INIT_CTL_NAME
546                 .procname       = "console_ratelimit",
547                 .data           = &libcfs_console_ratelimit,
548                 .maxlen         = sizeof(int),
549                 .mode           = 0644,
550                 .proc_handler   = &proc_dointvec
551         },
552         {
553                 INIT_CTL_NAME
554                 .procname       = "console_max_delay_centisecs",
555                 .maxlen         = sizeof(int),
556                 .mode           = 0644,
557                 .proc_handler   = &proc_console_max_delay_cs
558         },
559         {
560                 INIT_CTL_NAME
561                 .procname       = "console_min_delay_centisecs",
562                 .maxlen         = sizeof(int),
563                 .mode           = 0644,
564                 .proc_handler   = &proc_console_min_delay_cs
565         },
566         {
567                 INIT_CTL_NAME
568                 .procname       = "console_backoff",
569                 .maxlen         = sizeof(int),
570                 .mode           = 0644,
571                 .proc_handler   = &proc_console_backoff
572         },
573         {
574                 INIT_CTL_NAME
575                 .procname       = "debug_path",
576                 .data           = libcfs_debug_file_path_arr,
577                 .maxlen         = sizeof(libcfs_debug_file_path_arr),
578                 .mode           = 0644,
579                 .proc_handler   = &proc_dostring,
580         },
581         {
582                 INIT_CTL_NAME
583                 .procname       = "cpu_partition_table",
584                 .maxlen         = 128,
585                 .mode           = 0444,
586                 .proc_handler   = &proc_cpt_table,
587         },
588         {
589                 INIT_CTL_NAME
590                 .procname       = "cpu_partition_distance",
591                 .maxlen         = 128,
592                 .mode           = 0444,
593                 .proc_handler   = &proc_cpt_distance,
594         },
595         {
596                 INIT_CTL_NAME
597                 .procname       = "debug_log_upcall",
598                 .data           = lnet_debug_log_upcall,
599                 .maxlen         = sizeof(lnet_debug_log_upcall),
600                 .mode           = 0644,
601                 .proc_handler   = &proc_dostring,
602         },
603         {
604                 INIT_CTL_NAME
605                 .procname       = "lnet_memused",
606                 .data           = (int *)&libcfs_kmemory.counter,
607                 .maxlen         = sizeof(int),
608                 .mode           = 0444,
609                 .proc_handler   = &proc_dointvec,
610         },
611         {
612                 INIT_CTL_NAME
613                 .procname       = "catastrophe",
614                 .data           = &libcfs_catastrophe,
615                 .maxlen         = sizeof(int),
616                 .mode           = 0444,
617                 .proc_handler   = &proc_dointvec,
618         },
619         {
620                 INIT_CTL_NAME
621                 .procname       = "panic_on_lbug",
622                 .data           = &libcfs_panic_on_lbug,
623                 .maxlen         = sizeof(int),
624                 .mode           = 0644,
625                 .proc_handler   = &proc_dointvec,
626         },
627         {
628                 INIT_CTL_NAME
629                 .procname       = "dump_kernel",
630                 .maxlen         = 256,
631                 .mode           = 0200,
632                 .proc_handler   = &proc_dump_kernel,
633         },
634         {
635                 INIT_CTL_NAME
636                 .procname       = "daemon_file",
637                 .mode           = 0644,
638                 .maxlen         = 256,
639                 .proc_handler   = &proc_daemon_file,
640         },
641         {
642                 INIT_CTL_NAME
643                 .procname       = "debug_mb",
644                 .mode           = 0644,
645                 .proc_handler   = &proc_debug_mb,
646         },
647         {
648                 INIT_CTL_NAME
649                 .procname       = "watchdog_ratelimit",
650                 .data           = &libcfs_watchdog_ratelimit,
651                 .maxlen         = sizeof(int),
652                 .mode           = 0644,
653                 .proc_handler   = &proc_dointvec_minmax,
654                 .extra1         = &min_watchdog_ratelimit,
655                 .extra2         = &max_watchdog_ratelimit,
656         },
657         {
658                 INIT_CTL_NAME
659                 .procname       = "force_lbug",
660                 .data           = NULL,
661                 .maxlen         = 0,
662                 .mode           = 0200,
663                 .proc_handler   = &libcfs_force_lbug
664         },
665         {
666                 INIT_CTL_NAME
667                 .procname       = "fail_loc",
668                 .data           = &cfs_fail_loc,
669                 .maxlen         = sizeof(cfs_fail_loc),
670                 .mode           = 0644,
671                 .proc_handler   = &proc_fail_loc
672         },
673         {
674                 INIT_CTL_NAME
675                 .procname       = "fail_val",
676                 .data           = &cfs_fail_val,
677                 .maxlen         = sizeof(int),
678                 .mode           = 0644,
679                 .proc_handler   = &proc_dointvec
680         },
681         {
682                 INIT_CTL_NAME
683                 .procname       = "fail_err",
684                 .data           = &cfs_fail_err,
685                 .maxlen         = sizeof(cfs_fail_err),
686                 .mode           = 0644,
687                 .proc_handler   = &proc_dointvec,
688         },
689         {
690         }
691 };
692
693 #ifdef CONFIG_SYSCTL
694 static struct ctl_table top_table[] = {
695         {
696                 INIT_CTL_NAME
697                 .procname       = "lnet",
698                 .mode           = 0555,
699                 .data           = NULL,
700                 .maxlen         = 0,
701                 .child          = lnet_table,
702         },
703         { 0 }
704 };
705 #endif
706
707 static int insert_proc(void)
708 {
709 #ifdef CONFIG_SYSCTL
710         if (lnet_table_header == NULL)
711                 lnet_table_header = register_sysctl_table(top_table);
712 #endif
713         return 0;
714 }
715
716 static void remove_proc(void)
717 {
718 #ifdef CONFIG_SYSCTL
719         if (lnet_table_header != NULL)
720                 unregister_sysctl_table(lnet_table_header);
721
722         lnet_table_header = NULL;
723 #endif
724 }
725
726 static int __init libcfs_init(void)
727 {
728         int rc;
729
730         rc = libcfs_debug_init(5 * 1024 * 1024);
731         if (rc < 0) {
732                 printk(KERN_ERR "LustreError: libcfs_debug_init: %d\n", rc);
733                 return (rc);
734         }
735
736         rc = cfs_cpu_init();
737         if (rc != 0)
738                 goto cleanup_debug;
739
740         rc = misc_register(&libcfs_dev);
741         if (rc) {
742                 CERROR("misc_register: error %d\n", rc);
743                 goto cleanup_cpu;
744         }
745
746         rc = cfs_wi_startup();
747         if (rc) {
748                 CERROR("initialize workitem: error %d\n", rc);
749                 goto cleanup_deregister;
750         }
751
752         /* max to 4 threads, should be enough for rehash */
753         rc = min(cfs_cpt_weight(cfs_cpt_table, CFS_CPT_ANY), 4);
754         rc = cfs_wi_sched_create("cfs_rh", cfs_cpt_table, CFS_CPT_ANY,
755                                  rc, &cfs_sched_rehash);
756         if (rc != 0) {
757                 CERROR("Startup workitem scheduler: error: %d\n", rc);
758                 goto cleanup_deregister;
759         }
760
761         rc = cfs_crypto_register();
762         if (rc) {
763                 CERROR("cfs_crypto_regster: error %d\n", rc);
764                 goto cleanup_wi;
765         }
766
767
768         rc = insert_proc();
769         if (rc) {
770                 CERROR("insert_proc: error %d\n", rc);
771                 goto cleanup_crypto;
772         }
773
774         CDEBUG (D_OTHER, "portals setup OK\n");
775         return 0;
776 cleanup_crypto:
777         cfs_crypto_unregister();
778 cleanup_wi:
779         cfs_wi_shutdown();
780 cleanup_deregister:
781         misc_deregister(&libcfs_dev);
782 cleanup_cpu:
783         cfs_cpu_fini();
784 cleanup_debug:
785         libcfs_debug_cleanup();
786         return rc;
787 }
788
789 static void __exit libcfs_exit(void)
790 {
791         int rc;
792
793         remove_proc();
794
795         CDEBUG(D_MALLOC, "before Portals cleanup: kmem %d\n",
796                atomic_read(&libcfs_kmemory));
797
798         if (cfs_sched_rehash != NULL) {
799                 cfs_wi_sched_destroy(cfs_sched_rehash);
800                 cfs_sched_rehash = NULL;
801         }
802
803         cfs_crypto_unregister();
804         cfs_wi_shutdown();
805
806         misc_deregister(&libcfs_dev);
807
808         cfs_cpu_fini();
809
810         if (atomic_read(&libcfs_kmemory) != 0)
811                 CERROR("Portals memory leaked: %d bytes\n",
812                        atomic_read(&libcfs_kmemory));
813
814         rc = libcfs_debug_cleanup();
815         if (rc)
816                 printk(KERN_ERR "LustreError: libcfs_debug_cleanup: %d\n",
817                        rc);
818 }
819
820 MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
821 MODULE_DESCRIPTION("Lustre helper library");
822 MODULE_VERSION(LIBCFS_VERSION);
823 MODULE_LICENSE("GPL");
824
825 module_init(libcfs_init);
826 module_exit(libcfs_exit);