Whamcloud - gitweb
land b_eq on HEAD
[fs/lustre-release.git] / lustre / portals / 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 GMNAL:
418                 return  (PORTAL_SYMBOL_GET(kgmnal_ni));
419         case IBNAL:
420                 return  (PORTAL_SYMBOL_GET(kibnal_ni));
421         case TCPNAL:
422                 /* userspace NAL */
423                 return (NULL);
424         case SCIMACNAL:
425                 return  (PORTAL_SYMBOL_GET(kscimacnal_ni));
426         default:
427                 /* A warning to a naive caller */
428                 CERROR ("unknown nal: %d\n", nal);
429                 return (NULL);
430         }
431 }
432
433 void
434 kportal_put_ni (int nal)
435 {
436
437         switch (nal)
438         {
439         case QSWNAL:
440                 PORTAL_SYMBOL_PUT(kqswnal_ni);
441                 break;
442         case SOCKNAL:
443                 PORTAL_SYMBOL_PUT(ksocknal_ni);
444                 break;
445         case GMNAL:
446                 PORTAL_SYMBOL_PUT(kgmnal_ni);
447                 break;
448         case IBNAL:
449                 PORTAL_SYMBOL_PUT(kibnal_ni);
450                 break;
451         case TCPNAL:
452                 /* A lesson to a malicious caller */
453                 LBUG ();
454         case SCIMACNAL:
455                 PORTAL_SYMBOL_PUT(kscimacnal_ni);
456                 break;
457         default:
458                 CERROR ("unknown nal: %d\n", nal);
459         }
460 }
461
462 int
463 kportal_nal_register(int nal, nal_cmd_handler_t handler, void * private)
464 {
465         int rc = 0;
466
467         CDEBUG(D_IOCTL, "Register NAL %d, handler: %p\n", nal, handler);
468
469         if (nal > 0  && nal <= NAL_MAX_NR) {
470                 down(&nal_cmd_sem);
471                 if (nal_cmd[nal].nch_handler != NULL)
472                         rc = -EBUSY;
473                 else {
474                         nal_cmd[nal].nch_handler = handler;
475                         nal_cmd[nal].nch_private = private;
476                 }
477                 up(&nal_cmd_sem);
478         }
479         return rc;
480 }
481
482 int
483 kportal_nal_unregister(int nal)
484 {
485         int rc = 0;
486
487         CDEBUG(D_IOCTL, "Unregister NAL %d\n", nal);
488
489         if (nal > 0  && nal <= NAL_MAX_NR) {
490                 down(&nal_cmd_sem);
491                 nal_cmd[nal].nch_handler = NULL;
492                 nal_cmd[nal].nch_private = NULL;
493                 up(&nal_cmd_sem);
494         }
495         return rc;
496 }
497
498
499 static int kportal_ioctl(struct inode *inode, struct file *file,
500                          unsigned int cmd, unsigned long arg)
501 {
502         int err = 0;
503         char buf[1024];
504         struct portal_ioctl_data *data;
505         char str[PTL_NALFMT_SIZE];
506
507         ENTRY;
508
509         if (current->fsuid != 0)
510                 RETURN(err = -EACCES);
511
512         if ( _IOC_TYPE(cmd) != IOC_PORTAL_TYPE ||
513              _IOC_NR(cmd) < IOC_PORTAL_MIN_NR  ||
514              _IOC_NR(cmd) > IOC_PORTAL_MAX_NR ) {
515                 CDEBUG(D_IOCTL, "invalid ioctl ( type %d, nr %d, size %d )\n",
516                                 _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
517                 RETURN(-EINVAL);
518         }
519
520         if (portal_ioctl_getdata(buf, buf + 800, (void *)arg)) {
521                 CERROR("PORTALS ioctl: data error\n");
522                 RETURN(-EINVAL);
523         }
524
525         data = (struct portal_ioctl_data *)buf;
526
527         switch (cmd) {
528         case IOC_PORTAL_SET_DAEMON: 
529                 RETURN (portals_debug_set_daemon ( 
530                                         (unsigned int) data->ioc_count,
531                                         (unsigned int) data->ioc_inllen1,
532                                         (char *) data->ioc_inlbuf1,
533                                         (unsigned int) data->ioc_misc)); 
534         case IOC_PORTAL_GET_DEBUG: {
535                 __s32 size = portals_debug_copy_to_user(data->ioc_pbuf1,
536                                                         data->ioc_plen1);
537
538                 if (size < 0)
539                         RETURN(size);
540
541                 data->ioc_size = size;
542                 err = copy_to_user((char *)arg, data, sizeof(*data));
543                 RETURN(err);
544         }
545         case IOC_PORTAL_CLEAR_DEBUG:
546                 portals_debug_clear_buffer();
547                 RETURN(0);
548         case IOC_PORTAL_PANIC:
549                 if (!capable (CAP_SYS_BOOT))
550                         RETURN (-EPERM);
551                 panic("debugctl-invoked panic");
552                 RETURN(0);
553         case IOC_PORTAL_MARK_DEBUG:
554                 if (data->ioc_inlbuf1 == NULL ||
555                     data->ioc_inlbuf1[data->ioc_inllen1 - 1] != '\0')
556                         RETURN(-EINVAL);
557                 portals_debug_mark_buffer(data->ioc_inlbuf1);
558                 RETURN(0);
559         case IOC_PORTAL_PING: {
560                 void (*ping)(struct portal_ioctl_data *);
561
562                 CDEBUG(D_IOCTL, "doing %d pings to nid "LPX64" (%s)\n",
563                        data->ioc_count, data->ioc_nid,
564                        portals_nid2str(data->ioc_nal, data->ioc_nid, str));
565                 ping = PORTAL_SYMBOL_GET(kping_client);
566                 if (!ping)
567                         CERROR("PORTAL_SYMBOL_GET failed\n");
568                 else {
569                         ping(data);
570                         PORTAL_SYMBOL_PUT(kping_client);
571                 }
572                 RETURN(0);
573         }
574
575         case IOC_PORTAL_GET_NID: {
576                 const ptl_handle_ni_t *nip;
577                 ptl_process_id_t       pid;
578
579                 CDEBUG (D_IOCTL, "Getting nid for nal [%d]\n", data->ioc_nal);
580
581                 nip = kportal_get_ni (data->ioc_nal);
582                 if (nip == NULL)
583                         RETURN (-EINVAL);
584
585                 err = PtlGetId (*nip, &pid);
586                 LASSERT (err == PTL_OK);
587                 kportal_put_ni (data->ioc_nal);
588
589                 data->ioc_nid = pid.nid;
590                 if (copy_to_user ((char *)arg, data, sizeof (*data)))
591                         err = -EFAULT;
592                 break;
593         }
594
595         case IOC_PORTAL_NAL_CMD: {
596                 struct portals_cfg pcfg;
597
598                 LASSERT (data->ioc_plen1 == sizeof(pcfg));
599                 err = copy_from_user(&pcfg, (void *)data->ioc_pbuf1, 
600                                      sizeof(pcfg));
601                 if ( err ) {
602                         EXIT;
603                         return err;
604                 }
605
606                 CDEBUG (D_IOCTL, "nal command nal %d cmd %d\n", pcfg.pcfg_nal,
607                         pcfg.pcfg_command);
608                 err = kportal_nal_cmd(&pcfg);
609                 if (err == 0) {
610                         if (copy_to_user((char *)data->ioc_pbuf1, &pcfg, 
611                                          sizeof (pcfg)))
612                                 err = -EFAULT;
613                         if (copy_to_user((char *)arg, data, sizeof (*data)))
614                                 err = -EFAULT;
615                 }
616                 break;
617         }
618         case IOC_PORTAL_FAIL_NID: {
619                 const ptl_handle_ni_t *nip;
620
621                 CDEBUG (D_IOCTL, "fail nid: [%d] "LPU64" count %d\n",
622                         data->ioc_nal, data->ioc_nid, data->ioc_count);
623
624                 nip = kportal_get_ni (data->ioc_nal);
625                 if (nip == NULL)
626                         return (-EINVAL);
627
628                 err = PtlFailNid (*nip, data->ioc_nid, data->ioc_count);
629                 kportal_put_ni (data->ioc_nal);
630                 break;
631         }
632 #if LWT_SUPPORT
633         case IOC_PORTAL_LWT_CONTROL: 
634                 err = lwt_control (data->ioc_flags, data->ioc_misc);
635                 break;
636                 
637         case IOC_PORTAL_LWT_SNAPSHOT:
638                 err = lwt_snapshot (&data->ioc_nid,
639                                     &data->ioc_count, &data->ioc_misc,
640                                     data->ioc_pbuf1, data->ioc_plen1);
641                 if (err == 0 &&
642                     copy_to_user((char *)arg, data, sizeof (*data)))
643                         err = -EFAULT;
644                 break;
645                 
646         case IOC_PORTAL_LWT_LOOKUP_STRING:
647                 err = lwt_lookup_string (&data->ioc_count, data->ioc_pbuf1,
648                                          data->ioc_pbuf2, data->ioc_plen2);
649                 if (err == 0 &&
650                     copy_to_user((char *)arg, data, sizeof (*data)))
651                         err = -EFAULT;
652                 break;
653 #endif
654         case IOC_PORTAL_MEMHOG:
655                 if (!capable (CAP_SYS_ADMIN))
656                         err = -EPERM;
657                 else if (file->private_data == NULL) {
658                         err = -EINVAL;
659                 } else {
660                         kportal_memhog_free(file->private_data);
661                         err = kportal_memhog_alloc(file->private_data,
662                                                    data->ioc_count,
663                                                    data->ioc_flags);
664                         if (err != 0)
665                                 kportal_memhog_free(file->private_data);
666                 }
667                 break;
668
669         default:
670                 err = -EINVAL;
671                 break;
672         }
673
674         RETURN(err);
675 }
676
677
678 static struct file_operations portalsdev_fops = {
679         ioctl:   kportal_ioctl,
680         open:    kportal_psdev_open,
681         release: kportal_psdev_release
682 };
683
684
685 static struct miscdevice portal_dev = {
686         PORTAL_MINOR,
687         "portals",
688         &portalsdev_fops
689 };
690
691 extern int insert_proc(void);
692 extern void remove_proc(void);
693 MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>");
694 MODULE_DESCRIPTION("Portals v3.1");
695 MODULE_LICENSE("GPL");
696
697 static int init_kportals_module(void)
698 {
699         int rc;
700
701         rc = portals_debug_init(5 * 1024 * 1024);
702         if (rc < 0) {
703                 printk(KERN_ERR "LustreError: portals_debug_init: %d\n", rc);
704                 return (rc);
705         }
706
707 #if LWT_SUPPORT
708         rc = lwt_init();
709         if (rc != 0) {
710                 CERROR("lwt_init: error %d\n", rc);
711                 goto cleanup_debug;
712         }
713 #endif
714         sema_init(&nal_cmd_sem, 1);
715
716         rc = misc_register(&portal_dev);
717         if (rc) {
718                 CERROR("misc_register: error %d\n", rc);
719                 goto cleanup_lwt;
720         }
721
722         rc = PtlInit();
723         if (rc) {
724                 CERROR("PtlInit: error %d\n", rc);
725                 goto cleanup_deregister;
726         }
727
728         rc = insert_proc();
729         if (rc) {
730                 CERROR("insert_proc: error %d\n", rc);
731                 goto cleanup_fini;
732         }
733
734         rc = kportal_nal_register(ROUTER, kportal_router_cmd, NULL);
735         if (rc) {
736                 CERROR("kportal_nal_registre: ROUTER error %d\n", rc);
737                 goto cleanup_proc;
738         }
739
740         CDEBUG (D_OTHER, "portals setup OK\n");
741         return (0);
742
743  cleanup_proc:
744         remove_proc();
745  cleanup_fini:
746         PtlFini();
747  cleanup_deregister:
748         misc_deregister(&portal_dev);
749  cleanup_lwt:
750 #if LWT_SUPPORT
751         lwt_fini();
752  cleanup_debug:
753 #endif
754         portals_debug_cleanup();
755         return rc;
756 }
757
758 static void exit_kportals_module(void)
759 {
760         int rc;
761
762         kportal_nal_unregister(ROUTER);
763         remove_proc();
764         PtlFini();
765
766         CDEBUG(D_MALLOC, "before Portals cleanup: kmem %d\n",
767                atomic_read(&portal_kmemory));
768
769
770         rc = misc_deregister(&portal_dev);
771         if (rc)
772                 CERROR("misc_deregister error %d\n", rc);
773
774 #if LWT_SUPPORT
775         lwt_fini();
776 #endif
777
778         if (atomic_read(&portal_kmemory) != 0)
779                 CERROR("Portals memory leaked: %d bytes\n",
780                        atomic_read(&portal_kmemory));
781
782         rc = portals_debug_cleanup();
783         if (rc)
784                 printk(KERN_ERR "LustreError: portals_debug_cleanup: %d\n", rc);
785 }
786
787 EXPORT_SYMBOL(lib_dispatch);
788 EXPORT_SYMBOL(PtlMEAttach);
789 EXPORT_SYMBOL(PtlMEInsert);
790 EXPORT_SYMBOL(PtlMEUnlink);
791 EXPORT_SYMBOL(PtlEQAlloc);
792 EXPORT_SYMBOL(PtlMDAttach);
793 EXPORT_SYMBOL(PtlMDUnlink);
794 EXPORT_SYMBOL(PtlNIInit);
795 EXPORT_SYMBOL(PtlNIFini);
796 EXPORT_SYMBOL(PtlNIDebug);
797 EXPORT_SYMBOL(PtlInit);
798 EXPORT_SYMBOL(PtlFini);
799 EXPORT_SYMBOL(PtlPut);
800 EXPORT_SYMBOL(PtlGet);
801 EXPORT_SYMBOL(ptl_err_str);
802 EXPORT_SYMBOL(portal_subsystem_debug);
803 EXPORT_SYMBOL(portal_debug);
804 EXPORT_SYMBOL(portal_stack);
805 EXPORT_SYMBOL(portal_printk);
806 EXPORT_SYMBOL(portal_cerror);
807 EXPORT_SYMBOL(PtlEQWait);
808 EXPORT_SYMBOL(PtlEQFree);
809 EXPORT_SYMBOL(PtlEQGet);
810 EXPORT_SYMBOL(PtlGetId);
811 EXPORT_SYMBOL(PtlMDBind);
812 EXPORT_SYMBOL(lib_iov_nob);
813 EXPORT_SYMBOL(lib_copy_iov2buf);
814 EXPORT_SYMBOL(lib_copy_buf2iov);
815 EXPORT_SYMBOL(lib_extract_iov);
816 EXPORT_SYMBOL(lib_kiov_nob);
817 EXPORT_SYMBOL(lib_copy_kiov2buf);
818 EXPORT_SYMBOL(lib_copy_buf2kiov);
819 EXPORT_SYMBOL(lib_extract_kiov);
820 EXPORT_SYMBOL(lib_finalize);
821 EXPORT_SYMBOL(lib_parse);
822 EXPORT_SYMBOL(lib_fake_reply_msg);
823 EXPORT_SYMBOL(lib_init);
824 EXPORT_SYMBOL(lib_fini);
825 EXPORT_SYMBOL(portal_kmemory);
826 EXPORT_SYMBOL(kportal_daemonize);
827 EXPORT_SYMBOL(kportal_blockallsigs);
828 EXPORT_SYMBOL(kportal_nal_register);
829 EXPORT_SYMBOL(kportal_nal_unregister);
830 EXPORT_SYMBOL(kportal_assertion_failed);
831 EXPORT_SYMBOL(dispatch_name);
832 EXPORT_SYMBOL(kportal_get_ni);
833 EXPORT_SYMBOL(kportal_put_ni);
834 EXPORT_SYMBOL(kportal_nal_cmd);
835
836 module_init(init_kportals_module);
837 module_exit (exit_kportals_module);