Whamcloud - gitweb
55e1935985406df81067be6221e10002d637117e
[fs/lustre-release.git] / lnet / libcfs / module.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #ifndef EXPORT_SYMTAB
23 # define EXPORT_SYMTAB
24 #endif
25 #define DEBUG_SUBSYSTEM S_PORTALS
26
27 #include <linux/config.h>
28 #include <linux/module.h>
29 #include <linux/kernel.h>
30 #include <linux/mm.h>
31 #include <linux/string.h>
32 #include <linux/stat.h>
33 #include <linux/init.h>
34 #include <linux/errno.h>
35 #include <linux/smp_lock.h>
36 #include <linux/unistd.h>
37
38 #include <asm/system.h>
39 #include <asm/uaccess.h>
40
41 #include <linux/fs.h>
42 #include <linux/stat.h>
43 #include <asm/uaccess.h>
44 #include <asm/segment.h>
45 #include <linux/miscdevice.h>
46
47 #include <portals/lib-p30.h>
48 #include <portals/p30.h>
49 #include <linux/kp30.h>
50 #include <linux/portals_compat25.h>
51
52 #define PORTAL_MINOR 240
53
54 extern void (kping_client)(struct portal_ioctl_data *);
55
56 struct nal_cmd_handler {
57         nal_cmd_handler_t nch_handler;
58         void * nch_private;
59 };
60
61 static struct nal_cmd_handler nal_cmd[NAL_MAX_NR + 1];
62 struct semaphore nal_cmd_sem;
63
64 #ifdef PORTAL_DEBUG
65 void kportal_assertion_failed(char *expr, char *file, const char *func,
66                               const int line)
67 {
68         portals_debug_msg(0, D_EMERG, file, func, line, CDEBUG_STACK,
69                           "ASSERTION(%s) failed\n", expr);
70         LBUG_WITH_LOC(file, func, line);
71 }
72 #endif
73
74 void
75 kportal_daemonize (char *str) 
76 {
77 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,63))
78         daemonize(str);
79 #else
80         daemonize();
81         snprintf (current->comm, sizeof (current->comm), "%s", str);
82 #endif
83 }
84
85 void
86 kportal_memhog_free (struct portals_device_userstate *pdu)
87 {
88         struct page **level0p = &pdu->pdu_memhog_root_page;
89         struct page **level1p;
90         struct page **level2p;
91         int           count1;
92         int           count2;
93         
94         if (*level0p != NULL) {
95
96                 level1p = (struct page **)page_address(*level0p);
97                 count1 = 0;
98                 
99                 while (count1 < PAGE_SIZE/sizeof(struct page *) &&
100                        *level1p != NULL) {
101
102                         level2p = (struct page **)page_address(*level1p);
103                         count2 = 0;
104                         
105                         while (count2 < PAGE_SIZE/sizeof(struct page *) &&
106                                *level2p != NULL) {
107                                 
108                                 __free_page(*level2p);
109                                 pdu->pdu_memhog_pages--;
110                                 level2p++;
111                                 count2++;
112                         }
113                         
114                         __free_page(*level1p);
115                         pdu->pdu_memhog_pages--;
116                         level1p++;
117                         count1++;
118                 }
119                 
120                 __free_page(*level0p);
121                 pdu->pdu_memhog_pages--;
122
123                 *level0p = NULL;
124         }
125         
126         LASSERT (pdu->pdu_memhog_pages == 0);
127 }
128
129 int
130 kportal_memhog_alloc (struct portals_device_userstate *pdu, int npages, int flags)
131 {
132         struct page **level0p;
133         struct page **level1p;
134         struct page **level2p;
135         int           count1;
136         int           count2;
137         
138         LASSERT (pdu->pdu_memhog_pages == 0);
139         LASSERT (pdu->pdu_memhog_root_page == NULL);
140
141         if (npages < 0)
142                 return -EINVAL;
143
144         if (npages == 0)
145                 return 0;
146
147         level0p = &pdu->pdu_memhog_root_page;
148         *level0p = alloc_page(flags);
149         if (*level0p == NULL)
150                 return -ENOMEM;
151         pdu->pdu_memhog_pages++;
152
153         level1p = (struct page **)page_address(*level0p);
154         count1 = 0;
155         memset(level1p, 0, PAGE_SIZE);
156         
157         while (pdu->pdu_memhog_pages < npages &&
158                count1 < PAGE_SIZE/sizeof(struct page *)) {
159
160                 if (signal_pending(current))
161                         return (-EINTR);
162                 
163                 *level1p = alloc_page(flags);
164                 if (*level1p == NULL)
165                         return -ENOMEM;
166                 pdu->pdu_memhog_pages++;
167
168                 level2p = (struct page **)page_address(*level1p);
169                 count2 = 0;
170                 memset(level2p, 0, PAGE_SIZE);
171                 
172                 while (pdu->pdu_memhog_pages < npages &&
173                        count2 < PAGE_SIZE/sizeof(struct page *)) {
174                         
175                         if (signal_pending(current))
176                                 return (-EINTR);
177
178                         *level2p = alloc_page(flags);
179                         if (*level2p == NULL)
180                                 return (-ENOMEM);
181                         pdu->pdu_memhog_pages++;
182                         
183                         level2p++;
184                         count2++;
185                 }
186                 
187                 level1p++;
188                 count1++;
189         }
190
191         return 0;
192 }
193
194 void
195 kportal_blockallsigs ()
196 {
197         unsigned long  flags;
198
199         SIGNAL_MASK_LOCK(current, flags);
200         sigfillset(&current->blocked);
201         RECALC_SIGPENDING;
202         SIGNAL_MASK_UNLOCK(current, flags);
203 }
204
205 /* called when opening /dev/device */
206 static int kportal_psdev_open(struct inode * inode, struct file * file)
207 {
208         struct portals_device_userstate *pdu;
209         ENTRY;
210         
211         if (!inode)
212                 RETURN(-EINVAL);
213
214         PORTAL_MODULE_USE;
215
216         PORTAL_ALLOC(pdu, sizeof(*pdu));
217         if (pdu != NULL) {
218                 pdu->pdu_memhog_pages = 0;
219                 pdu->pdu_memhog_root_page = NULL;
220         }
221         file->private_data = pdu;
222         
223         RETURN(0);
224 }
225
226 /* called when closing /dev/device */
227 static int kportal_psdev_release(struct inode * inode, struct file * file)
228 {
229         struct portals_device_userstate *pdu;
230         ENTRY;
231
232         if (!inode)
233                 RETURN(-EINVAL);
234
235         pdu = file->private_data;
236         if (pdu != NULL) {
237                 kportal_memhog_free(pdu);
238                 PORTAL_FREE(pdu, sizeof(*pdu));
239         }
240         
241         PORTAL_MODULE_UNUSE;
242         RETURN(0);
243 }
244
245 static inline void freedata(void *data, int len)
246 {
247         PORTAL_FREE(data, len);
248 }
249
250 static int
251 kportal_add_route(int gateway_nalid, ptl_nid_t gateway_nid, 
252                   ptl_nid_t lo_nid, ptl_nid_t hi_nid)
253 {
254         int rc;
255         kpr_control_interface_t *ci;
256
257         ci = (kpr_control_interface_t *) PORTAL_SYMBOL_GET (kpr_control_interface);
258         if (ci == NULL)
259                 return (-ENODEV);
260
261         rc = ci->kprci_add_route (gateway_nalid, gateway_nid, lo_nid, hi_nid);
262
263         PORTAL_SYMBOL_PUT(kpr_control_interface);
264         return (rc);
265 }
266
267 static int
268 kportal_del_route(int gw_nalid, ptl_nid_t gw_nid, 
269                   ptl_nid_t lo, ptl_nid_t hi)
270 {
271         int rc;
272         kpr_control_interface_t *ci;
273
274         ci = (kpr_control_interface_t *)PORTAL_SYMBOL_GET(kpr_control_interface);
275         if (ci == NULL)
276                 return (-ENODEV);
277
278         rc = ci->kprci_del_route (gw_nalid, gw_nid, lo, hi);
279
280         PORTAL_SYMBOL_PUT(kpr_control_interface);
281         return (rc);
282 }
283
284 static int
285 kportal_notify_router (int gw_nalid, ptl_nid_t gw_nid,
286                        int alive, time_t when)
287 {
288         int rc;
289         kpr_control_interface_t *ci;
290
291         /* No error if router not preset.  Sysadmin is allowed to notify
292          * _everywhere_ when a NID boots or crashes, even if they know
293          * nothing of the peer. */
294         ci = (kpr_control_interface_t *)PORTAL_SYMBOL_GET(kpr_control_interface);
295         if (ci == NULL)
296                 return (0);
297
298         rc = ci->kprci_notify (gw_nalid, gw_nid, alive, when);
299
300         PORTAL_SYMBOL_PUT(kpr_control_interface);
301         return (rc);
302 }
303
304 static int
305 kportal_get_route(int index, __u32 *gateway_nalidp, ptl_nid_t *gateway_nidp,
306                   ptl_nid_t *lo_nidp, ptl_nid_t *hi_nidp, int *alivep)
307 {
308         int       gateway_nalid;
309         ptl_nid_t gateway_nid;
310         ptl_nid_t lo_nid;
311         ptl_nid_t hi_nid;
312         int       alive;
313         int       rc;
314         kpr_control_interface_t *ci;
315
316         ci = (kpr_control_interface_t *) PORTAL_SYMBOL_GET(kpr_control_interface);
317         if (ci == NULL)
318                 return (-ENODEV);
319
320         rc = ci->kprci_get_route(index, &gateway_nalid, &gateway_nid,
321                                  &lo_nid, &hi_nid, &alive);
322
323         if (rc == 0) {
324                 CDEBUG(D_IOCTL, "got route [%d] %d "LPX64":"LPX64" - "LPX64", %s\n",
325                        index, gateway_nalid, gateway_nid, lo_nid, hi_nid,
326                        alive ? "up" : "down");
327
328                 *gateway_nalidp = (__u32)gateway_nalid;
329                 *gateway_nidp   = gateway_nid;
330                 *lo_nidp        = lo_nid;
331                 *hi_nidp        = hi_nid;
332                 *alivep         = alive;
333         }
334
335         PORTAL_SYMBOL_PUT (kpr_control_interface);
336         return (rc);
337 }
338
339 static int 
340 kportal_router_cmd(struct portals_cfg *pcfg, void * private)
341 {
342         int err = -EINVAL;
343         ENTRY;
344
345         switch(pcfg->pcfg_command) {
346         default:
347                 CDEBUG(D_IOCTL, "Inappropriate cmd: %d\n", pcfg->pcfg_command);
348                 break;
349                 
350         case NAL_CMD_ADD_ROUTE:
351                 CDEBUG(D_IOCTL, "Adding route: [%d] "LPU64" : "LPU64" - "LPU64"\n",
352                        pcfg->pcfg_nal, pcfg->pcfg_nid, 
353                        pcfg->pcfg_nid2, pcfg->pcfg_nid3);
354                 err = kportal_add_route(pcfg->pcfg_gw_nal, pcfg->pcfg_nid,
355                                         pcfg->pcfg_nid2, pcfg->pcfg_nid3);
356                 break;
357
358         case NAL_CMD_DEL_ROUTE:
359                 CDEBUG (D_IOCTL, "Removing routes via [%d] "LPU64" : "LPU64" - "LPU64"\n",
360                         pcfg->pcfg_gw_nal, pcfg->pcfg_nid, 
361                         pcfg->pcfg_nid2, pcfg->pcfg_nid3);
362                 err = kportal_del_route (pcfg->pcfg_gw_nal, pcfg->pcfg_nid,
363                                          pcfg->pcfg_nid2, pcfg->pcfg_nid3);
364                 break;
365
366         case NAL_CMD_NOTIFY_ROUTER: {
367                 CDEBUG (D_IOCTL, "Notifying peer [%d] "LPU64" %s @ %ld\n",
368                         pcfg->pcfg_gw_nal, pcfg->pcfg_nid,
369                         pcfg->pcfg_flags ? "Enabling" : "Disabling",
370                         (time_t)pcfg->pcfg_nid3);
371                 
372                 err = kportal_notify_router (pcfg->pcfg_gw_nal, pcfg->pcfg_nid,
373                                              pcfg->pcfg_flags, 
374                                              (time_t)pcfg->pcfg_nid3);
375                 break;
376         }
377                 
378         case NAL_CMD_GET_ROUTE:
379                 CDEBUG (D_IOCTL, "Getting route [%d]\n", pcfg->pcfg_count);
380                 err = kportal_get_route(pcfg->pcfg_count, &pcfg->pcfg_gw_nal,
381                                         &pcfg->pcfg_nid, 
382                                         &pcfg->pcfg_nid2, &pcfg->pcfg_nid3,
383                                         &pcfg->pcfg_flags);
384                 break;
385         }
386         RETURN(err);
387 }
388
389 int
390 kportal_nal_cmd(struct portals_cfg *pcfg)
391 {
392         __u32 nal = pcfg->pcfg_nal;
393         int rc = -EINVAL;
394
395         ENTRY;
396
397         down(&nal_cmd_sem);
398         if (nal > 0 && nal <= NAL_MAX_NR && nal_cmd[nal].nch_handler) {
399                 CDEBUG(D_IOCTL, "calling handler nal: %d, cmd: %d\n", nal, 
400                        pcfg->pcfg_command);
401                 rc = nal_cmd[nal].nch_handler(pcfg, nal_cmd[nal].nch_private);
402         }
403         up(&nal_cmd_sem);
404         RETURN(rc);
405 }
406
407 ptl_handle_ni_t *
408 kportal_get_ni (int nal)
409 {
410
411         switch (nal)
412         {
413         case QSWNAL:
414                 return (PORTAL_SYMBOL_GET(kqswnal_ni));
415         case SOCKNAL:
416                 return (PORTAL_SYMBOL_GET(ksocknal_ni));
417         case TOENAL:
418                 return  (PORTAL_SYMBOL_GET(ktoenal_ni));
419         case GMNAL:
420                 return  (PORTAL_SYMBOL_GET(kgmnal_ni));
421         case IBNAL:
422                 return  (PORTAL_SYMBOL_GET(kibnal_ni));
423         case TCPNAL:
424                 /* userspace NAL */
425                 return (NULL);
426         case SCIMACNAL:
427                 return  (PORTAL_SYMBOL_GET(kscimacnal_ni));
428         default:
429                 /* A warning to a naive caller */
430                 CERROR ("unknown nal: %d\n", nal);
431                 return (NULL);
432         }
433 }
434
435 void
436 kportal_put_ni (int nal)
437 {
438
439         switch (nal)
440         {
441         case QSWNAL:
442                 PORTAL_SYMBOL_PUT(kqswnal_ni);
443                 break;
444         case SOCKNAL:
445                 PORTAL_SYMBOL_PUT(ksocknal_ni);
446                 break;
447         case TOENAL:
448                 PORTAL_SYMBOL_PUT(ktoenal_ni);
449                 break;
450         case GMNAL:
451                 PORTAL_SYMBOL_PUT(kgmnal_ni);
452                 break;
453         case IBNAL:
454                 PORTAL_SYMBOL_PUT(kibnal_ni);
455                 break;
456         case TCPNAL:
457                 /* A lesson to a malicious caller */
458                 LBUG ();
459         case SCIMACNAL:
460                 PORTAL_SYMBOL_PUT(kscimacnal_ni);
461                 break;
462         default:
463                 CERROR ("unknown nal: %d\n", nal);
464         }
465 }
466
467 int
468 kportal_nal_register(int nal, nal_cmd_handler_t handler, void * private)
469 {
470         int rc = 0;
471
472         CDEBUG(D_IOCTL, "Register NAL %d, handler: %p\n", nal, handler);
473
474         if (nal > 0  && nal <= NAL_MAX_NR) {
475                 down(&nal_cmd_sem);
476                 if (nal_cmd[nal].nch_handler != NULL)
477                         rc = -EBUSY;
478                 else {
479                         nal_cmd[nal].nch_handler = handler;
480                         nal_cmd[nal].nch_private = private;
481                 }
482                 up(&nal_cmd_sem);
483         }
484         return rc;
485 }
486
487 int
488 kportal_nal_unregister(int nal)
489 {
490         int rc = 0;
491
492         CDEBUG(D_IOCTL, "Unregister NAL %d\n", nal);
493
494         if (nal > 0  && nal <= NAL_MAX_NR) {
495                 down(&nal_cmd_sem);
496                 nal_cmd[nal].nch_handler = NULL;
497                 nal_cmd[nal].nch_private = NULL;
498                 up(&nal_cmd_sem);
499         }
500         return rc;
501 }
502
503
504 static int kportal_ioctl(struct inode *inode, struct file *file,
505                          unsigned int cmd, unsigned long arg)
506 {
507         int err = 0;
508         char buf[1024];
509         struct portal_ioctl_data *data;
510         char str[PTL_NALFMT_SIZE];
511
512         ENTRY;
513
514         if (current->fsuid != 0)
515                 RETURN(err = -EACCES);
516
517         if ( _IOC_TYPE(cmd) != IOC_PORTAL_TYPE ||
518              _IOC_NR(cmd) < IOC_PORTAL_MIN_NR  ||
519              _IOC_NR(cmd) > IOC_PORTAL_MAX_NR ) {
520                 CDEBUG(D_IOCTL, "invalid ioctl ( type %d, nr %d, size %d )\n",
521                                 _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
522                 RETURN(-EINVAL);
523         }
524
525         if (portal_ioctl_getdata(buf, buf + 800, (void *)arg)) {
526                 CERROR("PORTALS ioctl: data error\n");
527                 RETURN(-EINVAL);
528         }
529
530         data = (struct portal_ioctl_data *)buf;
531
532         switch (cmd) {
533         case IOC_PORTAL_SET_DAEMON: 
534                 RETURN (portals_debug_set_daemon ( 
535                                         (unsigned int) data->ioc_count,
536                                         (unsigned int) data->ioc_inllen1,
537                                         (char *) data->ioc_inlbuf1,
538                                         (unsigned int) data->ioc_misc)); 
539         case IOC_PORTAL_GET_DEBUG: {
540                 __s32 size = portals_debug_copy_to_user(data->ioc_pbuf1,
541                                                         data->ioc_plen1);
542
543                 if (size < 0)
544                         RETURN(size);
545
546                 data->ioc_size = size;
547                 err = copy_to_user((char *)arg, data, sizeof(*data));
548                 RETURN(err);
549         }
550         case IOC_PORTAL_CLEAR_DEBUG:
551                 portals_debug_clear_buffer();
552                 RETURN(0);
553         case IOC_PORTAL_PANIC:
554                 if (!capable (CAP_SYS_BOOT))
555                         RETURN (-EPERM);
556                 panic("debugctl-invoked panic");
557                 RETURN(0);
558         case IOC_PORTAL_MARK_DEBUG:
559                 if (data->ioc_inlbuf1 == NULL ||
560                     data->ioc_inlbuf1[data->ioc_inllen1 - 1] != '\0')
561                         RETURN(-EINVAL);
562                 portals_debug_mark_buffer(data->ioc_inlbuf1);
563                 RETURN(0);
564         case IOC_PORTAL_PING: {
565                 void (*ping)(struct portal_ioctl_data *);
566
567                 CDEBUG(D_IOCTL, "doing %d pings to nid "LPX64" (%s)\n",
568                        data->ioc_count, data->ioc_nid,
569                        portals_nid2str(data->ioc_nal, data->ioc_nid, str));
570                 ping = PORTAL_SYMBOL_GET(kping_client);
571                 if (!ping)
572                         CERROR("PORTAL_SYMBOL_GET failed\n");
573                 else {
574                         ping(data);
575                         PORTAL_SYMBOL_PUT(kping_client);
576                 }
577                 RETURN(0);
578         }
579
580         case IOC_PORTAL_GET_NID: {
581                 const ptl_handle_ni_t *nip;
582                 ptl_process_id_t       pid;
583
584                 CDEBUG (D_IOCTL, "Getting nid for nal [%d]\n", data->ioc_nal);
585
586                 nip = kportal_get_ni (data->ioc_nal);
587                 if (nip == NULL)
588                         RETURN (-EINVAL);
589
590                 err = PtlGetId (*nip, &pid);
591                 LASSERT (err == PTL_OK);
592                 kportal_put_ni (data->ioc_nal);
593
594                 data->ioc_nid = pid.nid;
595                 if (copy_to_user ((char *)arg, data, sizeof (*data)))
596                         err = -EFAULT;
597                 break;
598         }
599
600         case IOC_PORTAL_NAL_CMD: {
601                 struct portals_cfg pcfg;
602
603                 LASSERT (data->ioc_plen1 == sizeof(pcfg));
604                 err = copy_from_user(&pcfg, (void *)data->ioc_pbuf1, 
605                                      sizeof(pcfg));
606                 if ( err ) {
607                         EXIT;
608                         return err;
609                 }
610
611                 CDEBUG (D_IOCTL, "nal command nal %d cmd %d\n", pcfg.pcfg_nal,
612                         pcfg.pcfg_command);
613                 err = kportal_nal_cmd(&pcfg);
614                 if (err == 0) {
615                         if (copy_to_user((char *)data->ioc_pbuf1, &pcfg, 
616                                          sizeof (pcfg)))
617                                 err = -EFAULT;
618                         if (copy_to_user((char *)arg, data, sizeof (*data)))
619                                 err = -EFAULT;
620                 }
621                 break;
622         }
623         case IOC_PORTAL_FAIL_NID: {
624                 const ptl_handle_ni_t *nip;
625
626                 CDEBUG (D_IOCTL, "fail nid: [%d] "LPU64" count %d\n",
627                         data->ioc_nal, data->ioc_nid, data->ioc_count);
628
629                 nip = kportal_get_ni (data->ioc_nal);
630                 if (nip == NULL)
631                         return (-EINVAL);
632
633                 err = PtlFailNid (*nip, data->ioc_nid, data->ioc_count);
634                 kportal_put_ni (data->ioc_nal);
635                 break;
636         }
637 #if LWT_SUPPORT
638         case IOC_PORTAL_LWT_CONTROL: 
639                 err = lwt_control (data->ioc_flags, data->ioc_misc);
640                 break;
641                 
642         case IOC_PORTAL_LWT_SNAPSHOT:
643                 err = lwt_snapshot (&data->ioc_nid,
644                                     &data->ioc_count, &data->ioc_misc,
645                                     data->ioc_pbuf1, data->ioc_plen1);
646                 if (err == 0 &&
647                     copy_to_user((char *)arg, data, sizeof (*data)))
648                         err = -EFAULT;
649                 break;
650                 
651         case IOC_PORTAL_LWT_LOOKUP_STRING:
652                 err = lwt_lookup_string (&data->ioc_count, data->ioc_pbuf1,
653                                          data->ioc_pbuf2, data->ioc_plen2);
654                 if (err == 0 &&
655                     copy_to_user((char *)arg, data, sizeof (*data)))
656                         err = -EFAULT;
657                 break;
658 #endif
659         case IOC_PORTAL_MEMHOG:
660                 if (!capable (CAP_SYS_ADMIN))
661                         err = -EPERM;
662                 else if (file->private_data == NULL) {
663                         err = -EINVAL;
664                 } else {
665                         kportal_memhog_free(file->private_data);
666                         err = kportal_memhog_alloc(file->private_data,
667                                                    data->ioc_count,
668                                                    data->ioc_flags);
669                         if (err != 0)
670                                 kportal_memhog_free(file->private_data);
671                 }
672                 break;
673
674         default:
675                 err = -EINVAL;
676                 break;
677         }
678
679         RETURN(err);
680 }
681
682
683 static struct file_operations portalsdev_fops = {
684         ioctl:   kportal_ioctl,
685         open:    kportal_psdev_open,
686         release: kportal_psdev_release
687 };
688
689
690 static struct miscdevice portal_dev = {
691         PORTAL_MINOR,
692         "portals",
693         &portalsdev_fops
694 };
695
696 extern int insert_proc(void);
697 extern void remove_proc(void);
698 MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>");
699 MODULE_DESCRIPTION("Portals v3.1");
700 MODULE_LICENSE("GPL");
701
702 static int init_kportals_module(void)
703 {
704         int rc;
705
706         rc = portals_debug_init(5 * 1024 * 1024);
707         if (rc < 0) {
708                 printk(KERN_ERR "LustreError: portals_debug_init: %d\n", rc);
709                 return (rc);
710         }
711
712 #if LWT_SUPPORT
713         rc = lwt_init();
714         if (rc != 0) {
715                 CERROR("lwt_init: error %d\n", rc);
716                 goto cleanup_debug;
717         }
718 #endif
719         sema_init(&nal_cmd_sem, 1);
720
721         rc = misc_register(&portal_dev);
722         if (rc) {
723                 CERROR("misc_register: error %d\n", rc);
724                 goto cleanup_lwt;
725         }
726
727         rc = PtlInit();
728         if (rc) {
729                 CERROR("PtlInit: error %d\n", rc);
730                 goto cleanup_deregister;
731         }
732
733         rc = insert_proc();
734         if (rc) {
735                 CERROR("insert_proc: error %d\n", rc);
736                 goto cleanup_fini;
737         }
738
739         rc = kportal_nal_register(ROUTER, kportal_router_cmd, NULL);
740         if (rc) {
741                 CERROR("kportal_nal_registre: ROUTER error %d\n", rc);
742                 goto cleanup_proc;
743         }
744
745         CDEBUG (D_OTHER, "portals setup OK\n");
746         return (0);
747
748  cleanup_proc:
749         remove_proc();
750  cleanup_fini:
751         PtlFini();
752  cleanup_deregister:
753         misc_deregister(&portal_dev);
754  cleanup_lwt:
755 #if LWT_SUPPORT
756         lwt_fini();
757  cleanup_debug:
758 #endif
759         portals_debug_cleanup();
760         return rc;
761 }
762
763 static void exit_kportals_module(void)
764 {
765         int rc;
766
767         kportal_nal_unregister(ROUTER);
768         remove_proc();
769         PtlFini();
770
771         CDEBUG(D_MALLOC, "before Portals cleanup: kmem %d\n",
772                atomic_read(&portal_kmemory));
773
774
775         rc = misc_deregister(&portal_dev);
776         if (rc)
777                 CERROR("misc_deregister error %d\n", rc);
778
779 #if LWT_SUPPORT
780         lwt_fini();
781 #endif
782
783         if (atomic_read(&portal_kmemory) != 0)
784                 CERROR("Portals memory leaked: %d bytes\n",
785                        atomic_read(&portal_kmemory));
786
787         rc = portals_debug_cleanup();
788         if (rc)
789                 printk(KERN_ERR "LustreError: portals_debug_cleanup: %d\n", rc);
790 }
791
792 EXPORT_SYMBOL(lib_dispatch);
793 EXPORT_SYMBOL(PtlMEAttach);
794 EXPORT_SYMBOL(PtlMEInsert);
795 EXPORT_SYMBOL(PtlMEUnlink);
796 EXPORT_SYMBOL(PtlEQAlloc);
797 EXPORT_SYMBOL(PtlMDAttach);
798 EXPORT_SYMBOL(PtlMDUnlink);
799 EXPORT_SYMBOL(PtlNIInit);
800 EXPORT_SYMBOL(PtlNIFini);
801 EXPORT_SYMBOL(PtlNIDebug);
802 EXPORT_SYMBOL(PtlInit);
803 EXPORT_SYMBOL(PtlFini);
804 EXPORT_SYMBOL(PtlPut);
805 EXPORT_SYMBOL(PtlGet);
806 EXPORT_SYMBOL(ptl_err_str);
807 EXPORT_SYMBOL(portal_subsystem_debug);
808 EXPORT_SYMBOL(portal_debug);
809 EXPORT_SYMBOL(portal_stack);
810 EXPORT_SYMBOL(portal_printk);
811 EXPORT_SYMBOL(portal_cerror);
812 EXPORT_SYMBOL(PtlEQWait);
813 EXPORT_SYMBOL(PtlEQFree);
814 EXPORT_SYMBOL(PtlEQGet);
815 EXPORT_SYMBOL(PtlGetId);
816 EXPORT_SYMBOL(PtlMDBind);
817 EXPORT_SYMBOL(lib_iov_nob);
818 EXPORT_SYMBOL(lib_copy_iov2buf);
819 EXPORT_SYMBOL(lib_copy_buf2iov);
820 EXPORT_SYMBOL(lib_kiov_nob);
821 EXPORT_SYMBOL(lib_copy_kiov2buf);
822 EXPORT_SYMBOL(lib_copy_buf2kiov);
823 EXPORT_SYMBOL(lib_finalize);
824 EXPORT_SYMBOL(lib_parse);
825 EXPORT_SYMBOL(lib_fake_reply_msg);
826 EXPORT_SYMBOL(lib_init);
827 EXPORT_SYMBOL(lib_fini);
828 EXPORT_SYMBOL(portal_kmemory);
829 EXPORT_SYMBOL(kportal_daemonize);
830 EXPORT_SYMBOL(kportal_blockallsigs);
831 EXPORT_SYMBOL(kportal_nal_register);
832 EXPORT_SYMBOL(kportal_nal_unregister);
833 EXPORT_SYMBOL(kportal_assertion_failed);
834 EXPORT_SYMBOL(dispatch_name);
835 EXPORT_SYMBOL(kportal_get_ni);
836 EXPORT_SYMBOL(kportal_put_ni);
837 EXPORT_SYMBOL(kportal_nal_cmd);
838
839 module_init(init_kportals_module);
840 module_exit (exit_kportals_module);