Whamcloud - gitweb
smash the HEAD with the contents of b_cmd. HEAD_PRE_CMD_SMASH and
[fs/lustre-release.git] / lnet / lnet / 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/kpr.h>
51 #include <linux/portals_compat25.h>
52
53 extern void (kping_client)(struct portal_ioctl_data *);
54
55 struct nal_cmd_handler {
56         nal_cmd_handler_t nch_handler;
57         void * nch_private;
58 };
59
60 static struct nal_cmd_handler nal_cmd[NAL_MAX_NR + 1];
61 static DECLARE_MUTEX(nal_cmd_sem);
62
63
64 static int
65 kportal_add_route(int gateway_nalid, ptl_nid_t gateway_nid, 
66                   ptl_nid_t lo_nid, ptl_nid_t hi_nid)
67 {
68         int rc;
69         kpr_control_interface_t *ci;
70
71         ci = (kpr_control_interface_t *) PORTAL_SYMBOL_GET (kpr_control_interface);
72         if (ci == NULL)
73                 return (-ENODEV);
74
75         rc = ci->kprci_add_route (gateway_nalid, gateway_nid, lo_nid, hi_nid);
76
77         PORTAL_SYMBOL_PUT(kpr_control_interface);
78         return (rc);
79 }
80
81 static int
82 kportal_del_route(int gw_nalid, ptl_nid_t gw_nid, 
83                   ptl_nid_t lo, ptl_nid_t hi)
84 {
85         int rc;
86         kpr_control_interface_t *ci;
87
88         ci = (kpr_control_interface_t *)PORTAL_SYMBOL_GET(kpr_control_interface);
89         if (ci == NULL)
90                 return (-ENODEV);
91
92         rc = ci->kprci_del_route (gw_nalid, gw_nid, lo, hi);
93
94         PORTAL_SYMBOL_PUT(kpr_control_interface);
95         return (rc);
96 }
97
98 static int
99 kportal_notify_router (int gw_nalid, ptl_nid_t gw_nid,
100                        int alive, time_t when)
101 {
102         int rc;
103         kpr_control_interface_t *ci;
104
105         /* No error if router not preset.  Sysadmin is allowed to notify
106          * _everywhere_ when a NID boots or crashes, even if they know
107          * nothing of the peer. */
108         ci = (kpr_control_interface_t *)PORTAL_SYMBOL_GET(kpr_control_interface);
109         if (ci == NULL)
110                 return (0);
111
112         rc = ci->kprci_notify (gw_nalid, gw_nid, alive, when);
113
114         PORTAL_SYMBOL_PUT(kpr_control_interface);
115         return (rc);
116 }
117
118 static int
119 kportal_get_route(int index, __u32 *gateway_nalidp, ptl_nid_t *gateway_nidp,
120                   ptl_nid_t *lo_nidp, ptl_nid_t *hi_nidp, int *alivep)
121 {
122         int       gateway_nalid;
123         ptl_nid_t gateway_nid;
124         ptl_nid_t lo_nid;
125         ptl_nid_t hi_nid;
126         int       alive;
127         int       rc;
128         kpr_control_interface_t *ci;
129
130         ci = (kpr_control_interface_t *) PORTAL_SYMBOL_GET(kpr_control_interface);
131         if (ci == NULL)
132                 return (-ENODEV);
133
134         rc = ci->kprci_get_route(index, &gateway_nalid, &gateway_nid,
135                                  &lo_nid, &hi_nid, &alive);
136
137         if (rc == 0) {
138                 CDEBUG(D_IOCTL, "got route [%d] %d "LPX64":"LPX64" - "LPX64", %s\n",
139                        index, gateway_nalid, gateway_nid, lo_nid, hi_nid,
140                        alive ? "up" : "down");
141
142                 *gateway_nalidp = (__u32)gateway_nalid;
143                 *gateway_nidp   = gateway_nid;
144                 *lo_nidp        = lo_nid;
145                 *hi_nidp        = hi_nid;
146                 *alivep         = alive;
147         }
148
149         PORTAL_SYMBOL_PUT (kpr_control_interface);
150         return (rc);
151 }
152
153 static int 
154 kportal_router_cmd(struct portals_cfg *pcfg, void * private)
155 {
156         int err = -EINVAL;
157         ENTRY;
158
159         switch(pcfg->pcfg_command) {
160         default:
161                 CDEBUG(D_IOCTL, "Inappropriate cmd: %d\n", pcfg->pcfg_command);
162                 break;
163                 
164         case NAL_CMD_ADD_ROUTE:
165                 CDEBUG(D_IOCTL, "Adding route: [%d] "LPU64" : "LPU64" - "LPU64"\n",
166                        pcfg->pcfg_nal, pcfg->pcfg_nid, 
167                        pcfg->pcfg_nid2, pcfg->pcfg_nid3);
168                 err = kportal_add_route(pcfg->pcfg_gw_nal, pcfg->pcfg_nid,
169                                         pcfg->pcfg_nid2, pcfg->pcfg_nid3);
170                 break;
171
172         case NAL_CMD_DEL_ROUTE:
173                 CDEBUG (D_IOCTL, "Removing routes via [%d] "LPU64" : "LPU64" - "LPU64"\n",
174                         pcfg->pcfg_gw_nal, pcfg->pcfg_nid, 
175                         pcfg->pcfg_nid2, pcfg->pcfg_nid3);
176                 err = kportal_del_route (pcfg->pcfg_gw_nal, pcfg->pcfg_nid,
177                                          pcfg->pcfg_nid2, pcfg->pcfg_nid3);
178                 break;
179
180         case NAL_CMD_NOTIFY_ROUTER: {
181                 CDEBUG (D_IOCTL, "Notifying peer [%d] "LPU64" %s @ %ld\n",
182                         pcfg->pcfg_gw_nal, pcfg->pcfg_nid,
183                         pcfg->pcfg_flags ? "Enabling" : "Disabling",
184                         (time_t)pcfg->pcfg_nid3);
185                 
186                 err = kportal_notify_router (pcfg->pcfg_gw_nal, pcfg->pcfg_nid,
187                                              pcfg->pcfg_flags, 
188                                              (time_t)pcfg->pcfg_nid3);
189                 break;
190         }
191                 
192         case NAL_CMD_GET_ROUTE:
193                 CDEBUG (D_IOCTL, "Getting route [%d]\n", pcfg->pcfg_count);
194                 err = kportal_get_route(pcfg->pcfg_count, &pcfg->pcfg_gw_nal,
195                                         &pcfg->pcfg_nid, 
196                                         &pcfg->pcfg_nid2, &pcfg->pcfg_nid3,
197                                         &pcfg->pcfg_flags);
198                 break;
199         }
200         RETURN(err);
201 }
202
203 int
204 kportal_nal_cmd(struct portals_cfg *pcfg)
205 {
206         __u32 nal = pcfg->pcfg_nal;
207         int rc = -EINVAL;
208
209         ENTRY;
210
211         down(&nal_cmd_sem);
212         if (nal > 0 && nal <= NAL_MAX_NR && nal_cmd[nal].nch_handler) {
213                 CDEBUG(D_IOCTL, "calling handler nal: %d, cmd: %d\n", nal, 
214                        pcfg->pcfg_command);
215                 rc = nal_cmd[nal].nch_handler(pcfg, nal_cmd[nal].nch_private);
216         }
217         up(&nal_cmd_sem);
218         RETURN(rc);
219 }
220
221 ptl_handle_ni_t *
222 kportal_get_ni (int nal)
223 {
224
225         switch (nal)
226         {
227         case QSWNAL:
228                 return (PORTAL_SYMBOL_GET(kqswnal_ni));
229         case SOCKNAL:
230                 return (PORTAL_SYMBOL_GET(ksocknal_ni));
231         case GMNAL:
232                 return  (PORTAL_SYMBOL_GET(kgmnal_ni));
233         case IBNAL:
234                 return  (PORTAL_SYMBOL_GET(kibnal_ni));
235         case TCPNAL:
236                 /* userspace NAL */
237                 return (NULL);
238         case SCIMACNAL:
239                 return  (PORTAL_SYMBOL_GET(kscimacnal_ni));
240         default:
241                 /* A warning to a naive caller */
242                 CERROR ("unknown nal: %d\n", nal);
243                 return (NULL);
244         }
245 }
246
247 void
248 kportal_put_ni (int nal)
249 {
250
251         switch (nal)
252         {
253         case QSWNAL:
254                 PORTAL_SYMBOL_PUT(kqswnal_ni);
255                 break;
256         case SOCKNAL:
257                 PORTAL_SYMBOL_PUT(ksocknal_ni);
258                 break;
259         case GMNAL:
260                 PORTAL_SYMBOL_PUT(kgmnal_ni);
261                 break;
262         case IBNAL:
263                 PORTAL_SYMBOL_PUT(kibnal_ni);
264                 break;
265         case TCPNAL:
266                 /* A lesson to a malicious caller */
267                 LBUG ();
268         case SCIMACNAL:
269                 PORTAL_SYMBOL_PUT(kscimacnal_ni);
270                 break;
271         default:
272                 CERROR ("unknown nal: %d\n", nal);
273         }
274 }
275
276 int
277 kportal_nal_register(int nal, nal_cmd_handler_t handler, void * private)
278 {
279         int rc = 0;
280
281         CDEBUG(D_IOCTL, "Register NAL %d, handler: %p\n", nal, handler);
282
283         if (nal > 0  && nal <= NAL_MAX_NR) {
284                 down(&nal_cmd_sem);
285                 if (nal_cmd[nal].nch_handler != NULL)
286                         rc = -EBUSY;
287                 else {
288                         nal_cmd[nal].nch_handler = handler;
289                         nal_cmd[nal].nch_private = private;
290                 }
291                 up(&nal_cmd_sem);
292         }
293         return rc;
294 }
295
296 int
297 kportal_nal_unregister(int nal)
298 {
299         int rc = 0;
300
301         CDEBUG(D_IOCTL, "Unregister NAL %d\n", nal);
302
303         if (nal > 0  && nal <= NAL_MAX_NR) {
304                 down(&nal_cmd_sem);
305                 nal_cmd[nal].nch_handler = NULL;
306                 nal_cmd[nal].nch_private = NULL;
307                 up(&nal_cmd_sem);
308         }
309         return rc;
310 }
311
312 static int kportal_ioctl(struct portal_ioctl_data *data, 
313                          unsigned int cmd, unsigned long arg)
314 {
315         int err = 0;
316         char str[PTL_NALFMT_SIZE];
317         ENTRY;
318
319         switch (cmd) {
320         case IOC_PORTAL_PING: {
321                 void (*ping)(struct portal_ioctl_data *);
322
323                 CDEBUG(D_IOCTL, "doing %d pings to nid "LPX64" (%s)\n",
324                        data->ioc_count, data->ioc_nid,
325                        portals_nid2str(data->ioc_nal, data->ioc_nid, str));
326                 ping = PORTAL_SYMBOL_GET(kping_client);
327                 if (!ping)
328                         CERROR("PORTAL_SYMBOL_GET failed\n");
329                 else {
330                         ping(data);
331                         PORTAL_SYMBOL_PUT(kping_client);
332                 }
333                 RETURN(0);
334         }
335
336         case IOC_PORTAL_GET_NID: {
337                 const ptl_handle_ni_t *nip;
338                 ptl_process_id_t       pid;
339
340                 CDEBUG (D_IOCTL, "Getting nid for nal [%d]\n", data->ioc_nal);
341
342                 nip = kportal_get_ni (data->ioc_nal);
343                 if (nip == NULL)
344                         RETURN (-EINVAL);
345
346                 err = PtlGetId (*nip, &pid);
347                 LASSERT (err == PTL_OK);
348                 kportal_put_ni (data->ioc_nal);
349
350                 data->ioc_nid = pid.nid;
351                 if (copy_to_user ((char *)arg, data, sizeof (*data)))
352                         err = -EFAULT;
353                 break;
354         }
355
356         case IOC_PORTAL_NAL_CMD: {
357                 struct portals_cfg pcfg;
358
359                 LASSERT (data->ioc_plen1 == sizeof(pcfg));
360                 err = copy_from_user(&pcfg, (void *)data->ioc_pbuf1, 
361                                      sizeof(pcfg));
362                 if ( err ) {
363                         EXIT;
364                         return err;
365                 }
366
367                 CDEBUG (D_IOCTL, "nal command nal %d cmd %d\n", pcfg.pcfg_nal,
368                         pcfg.pcfg_command);
369                 err = kportal_nal_cmd(&pcfg);
370                 if (err == 0) {
371                         if (copy_to_user((char *)data->ioc_pbuf1, &pcfg, 
372                                          sizeof (pcfg)))
373                                 err = -EFAULT;
374                         if (copy_to_user((char *)arg, data, sizeof (*data)))
375                                 err = -EFAULT;
376                 }
377                 break;
378         }
379         case IOC_PORTAL_FAIL_NID: {
380                 const ptl_handle_ni_t *nip;
381
382                 CDEBUG (D_IOCTL, "fail nid: [%d] "LPU64" count %d\n",
383                         data->ioc_nal, data->ioc_nid, data->ioc_count);
384
385                 nip = kportal_get_ni (data->ioc_nal);
386                 if (nip == NULL)
387                         return (-EINVAL);
388
389                 err = PtlFailNid (*nip, data->ioc_nid, data->ioc_count);
390                 kportal_put_ni (data->ioc_nal);
391                 break;
392         }
393         default:
394                 err = -EINVAL;
395                 break;
396         }
397
398         RETURN(err);
399 }
400
401 DECLARE_IOCTL_HANDLER(kportal_ioctl_handler, kportal_ioctl);
402
403 static int init_kportals_module(void)
404 {
405         int rc;
406         ENTRY;
407
408         rc = PtlInit(NULL);
409         if (rc) {
410                 CERROR("PtlInit: error %d\n", rc);
411                 RETURN(rc);
412         }
413
414         rc = kportal_nal_register(ROUTER, kportal_router_cmd, NULL);
415         if (rc) {
416                 PtlFini();
417                 CERROR("kportal_nal_registre: ROUTER error %d\n", rc);
418         }
419
420         if (rc == 0)
421                 libcfs_register_ioctl(&kportal_ioctl_handler);
422
423         RETURN(rc);
424 }
425
426 static void exit_kportals_module(void)
427 {
428         libcfs_deregister_ioctl(&kportal_ioctl_handler);
429         kportal_nal_unregister(ROUTER);
430         PtlFini();
431 }
432
433 EXPORT_SYMBOL(kportal_nal_register);
434 EXPORT_SYMBOL(kportal_nal_unregister);
435 EXPORT_SYMBOL(kportal_get_ni);
436 EXPORT_SYMBOL(kportal_put_ni);
437 EXPORT_SYMBOL(kportal_nal_cmd);
438
439 EXPORT_SYMBOL(ptl_err_str);
440 EXPORT_SYMBOL(lib_dispatch);
441 EXPORT_SYMBOL(PtlMEAttach);
442 EXPORT_SYMBOL(PtlMEInsert);
443 EXPORT_SYMBOL(PtlMEUnlink);
444 EXPORT_SYMBOL(PtlEQAlloc);
445 EXPORT_SYMBOL(PtlMDAttach);
446 EXPORT_SYMBOL(PtlMDUnlink);
447 EXPORT_SYMBOL(PtlNIInit);
448 EXPORT_SYMBOL(PtlNIFini);
449 EXPORT_SYMBOL(PtlNIDebug);
450 EXPORT_SYMBOL(PtlInit);
451 EXPORT_SYMBOL(PtlFini);
452 EXPORT_SYMBOL(PtlSnprintHandle);
453 EXPORT_SYMBOL(PtlPut);
454 EXPORT_SYMBOL(PtlGet);
455 EXPORT_SYMBOL(PtlEQWait);
456 EXPORT_SYMBOL(PtlEQFree);
457 EXPORT_SYMBOL(PtlEQGet);
458 EXPORT_SYMBOL(PtlGetId);
459 EXPORT_SYMBOL(PtlMDBind);
460 EXPORT_SYMBOL(lib_iov_nob);
461 EXPORT_SYMBOL(lib_copy_iov2buf);
462 EXPORT_SYMBOL(lib_copy_buf2iov);
463 EXPORT_SYMBOL(lib_extract_iov);
464 EXPORT_SYMBOL(lib_kiov_nob);
465 EXPORT_SYMBOL(lib_copy_kiov2buf);
466 EXPORT_SYMBOL(lib_copy_buf2kiov);
467 EXPORT_SYMBOL(lib_extract_kiov);
468 EXPORT_SYMBOL(lib_finalize);
469 EXPORT_SYMBOL(lib_parse);
470 EXPORT_SYMBOL(lib_create_reply_msg);
471 EXPORT_SYMBOL(lib_init);
472 EXPORT_SYMBOL(lib_fini);
473 EXPORT_SYMBOL(dispatch_name);
474
475 MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>");
476 MODULE_DESCRIPTION("Portals v3.1");
477 MODULE_LICENSE("GPL");
478 module_init(init_kportals_module);
479 module_exit(exit_kportals_module);