Whamcloud - gitweb
694bbb4031e5f30a1c551232d033b2c6b54579dc
[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.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, 2015, 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
39 #include <libcfs/libcfs.h>
40 #include <libcfs/libcfs_crypto.h>
41 #include <lnet/lib-lnet.h>
42
43 static DECLARE_RWSEM(ioctl_list_sem);
44 static LIST_HEAD(ioctl_list);
45
46 int libcfs_register_ioctl(struct libcfs_ioctl_handler *hand)
47 {
48         int rc = 0;
49
50         down_write(&ioctl_list_sem);
51         if (!list_empty(&hand->item))
52                 rc = -EBUSY;
53         else
54                 list_add_tail(&hand->item, &ioctl_list);
55         up_write(&ioctl_list_sem);
56
57         return rc;
58 }
59 EXPORT_SYMBOL(libcfs_register_ioctl);
60
61 int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand)
62 {
63         int rc = 0;
64
65         down_write(&ioctl_list_sem);
66         if (list_empty(&hand->item))
67                 rc = -ENOENT;
68         else
69                 list_del_init(&hand->item);
70         up_write(&ioctl_list_sem);
71
72         return rc;
73 }
74 EXPORT_SYMBOL(libcfs_deregister_ioctl);
75
76 int libcfs_ioctl(unsigned long cmd, void __user *uparam)
77 {
78         struct libcfs_ioctl_data *data = NULL;
79         struct libcfs_ioctl_hdr  *hdr;
80         int                       err;
81         ENTRY;
82
83         /* 'cmd' and permissions get checked in our arch-specific caller */
84         err = libcfs_ioctl_getdata(&hdr, uparam);
85         if (err != 0) {
86                 CDEBUG_LIMIT(D_ERROR,
87                              "libcfs ioctl: data header error %d\n", err);
88                 RETURN(err);
89         }
90
91         if (hdr->ioc_version == LIBCFS_IOCTL_VERSION) {
92                 /* The libcfs_ioctl_data_adjust() function performs adjustment
93                  * operations on the libcfs_ioctl_data structure to make
94                  * it usable by the code.  This doesn't need to be called
95                  * for new data structures added. */
96                 data = container_of(hdr, struct libcfs_ioctl_data, ioc_hdr);
97                 err = libcfs_ioctl_data_adjust(data);
98                 if (err != 0)
99                         GOTO(out, err);
100         }
101
102         CDEBUG(D_IOCTL, "libcfs ioctl cmd %lu\n", cmd);
103         switch (cmd) {
104         case IOC_LIBCFS_CLEAR_DEBUG:
105                 libcfs_debug_clear_buffer();
106                 break;
107         case IOC_LIBCFS_MARK_DEBUG:
108                 if (data == NULL ||
109                     data->ioc_inlbuf1 == NULL ||
110                     data->ioc_inlbuf1[data->ioc_inllen1 - 1] != '\0')
111                         GOTO(out, err = -EINVAL);
112
113                 libcfs_debug_mark_buffer(data->ioc_inlbuf1);
114                 break;
115
116         default: {
117                 struct libcfs_ioctl_handler *hand;
118
119                 err = -EINVAL;
120                 down_read(&ioctl_list_sem);
121                 list_for_each_entry(hand, &ioctl_list, item) {
122                         err = hand->handle_ioctl(cmd, hdr);
123                         if (err == -EINVAL)
124                                 continue;
125
126                         if (err == 0) {
127                                 if (copy_to_user(uparam, hdr, hdr->ioc_len))
128                                         err = -EFAULT;
129                         }
130                         break;
131                 }
132                 up_read(&ioctl_list_sem);
133                 break; }
134         }
135 out:
136         LIBCFS_FREE(hdr, hdr->ioc_len);
137         RETURN(err);
138 }
139
140 static int __init libcfs_init(void)
141 {
142         int rc;
143
144         rc = libcfs_debug_init(5 * 1024 * 1024);
145         if (rc < 0) {
146                 printk(KERN_ERR "LustreError: libcfs_debug_init: %d\n", rc);
147                 return (rc);
148         }
149
150         rc = cfs_cpu_init();
151         if (rc != 0)
152                 goto cleanup_debug;
153
154         rc = misc_register(&libcfs_dev);
155         if (rc) {
156                 CERROR("misc_register: error %d\n", rc);
157                 goto cleanup_cpu;
158         }
159
160         rc = cfs_wi_startup();
161         if (rc) {
162                 CERROR("initialize workitem: error %d\n", rc);
163                 goto cleanup_deregister;
164         }
165
166         /* max to 4 threads, should be enough for rehash */
167         rc = min(cfs_cpt_weight(cfs_cpt_table, CFS_CPT_ANY), 4);
168         rc = cfs_wi_sched_create("cfs_rh", cfs_cpt_table, CFS_CPT_ANY,
169                                  rc, &cfs_sched_rehash);
170         if (rc != 0) {
171                 CERROR("Startup workitem scheduler: error: %d\n", rc);
172                 goto cleanup_deregister;
173         }
174
175         rc = cfs_crypto_register();
176         if (rc) {
177                 CERROR("cfs_crypto_regster: error %d\n", rc);
178                 goto cleanup_wi;
179         }
180
181
182         rc = insert_proc();
183         if (rc) {
184                 CERROR("insert_proc: error %d\n", rc);
185                 goto cleanup_crypto;
186         }
187
188         CDEBUG (D_OTHER, "portals setup OK\n");
189         return 0;
190 cleanup_crypto:
191         cfs_crypto_unregister();
192 cleanup_wi:
193         cfs_wi_shutdown();
194 cleanup_deregister:
195         misc_deregister(&libcfs_dev);
196 cleanup_cpu:
197         cfs_cpu_fini();
198 cleanup_debug:
199         libcfs_debug_cleanup();
200         return rc;
201 }
202
203 static void __exit libcfs_exit(void)
204 {
205         int rc;
206
207         remove_proc();
208
209         CDEBUG(D_MALLOC, "before Portals cleanup: kmem %d\n",
210                atomic_read(&libcfs_kmemory));
211
212         if (cfs_sched_rehash != NULL) {
213                 cfs_wi_sched_destroy(cfs_sched_rehash);
214                 cfs_sched_rehash = NULL;
215         }
216
217         cfs_crypto_unregister();
218         cfs_wi_shutdown();
219
220         misc_deregister(&libcfs_dev);
221
222         cfs_cpu_fini();
223
224         if (atomic_read(&libcfs_kmemory) != 0)
225                 CERROR("Portals memory leaked: %d bytes\n",
226                        atomic_read(&libcfs_kmemory));
227
228         rc = libcfs_debug_cleanup();
229         if (rc)
230                 printk(KERN_ERR "LustreError: libcfs_debug_cleanup: %d\n",
231                        rc);
232 }
233
234 MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
235 MODULE_DESCRIPTION("Lustre helper library");
236 MODULE_VERSION(LIBCFS_VERSION);
237 MODULE_LICENSE("GPL");
238
239 module_init(libcfs_init);
240 module_exit(libcfs_exit);