Whamcloud - gitweb
* Modified socknal to...
[fs/lustre-release.git] / lustre / portals / tests / sping_srv.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2002, Lawrence Livermore National Labs (LLNL)
5  * Author: Brian Behlendorf <behlendorf1@llnl.gov>
6  *         Amey Inamdar     <amey@calsoftinc.com>
7  *         Kedar Sovani     <kedar@calsoftinc.com>
8  *
9  *
10  * This file is part of Portals, http://www.sf.net/projects/lustre/
11  *
12  * Portals is free software; you can redistribute it and/or
13  * modify it under the terms of version 2 of the GNU General Public
14  * License as published by the Free Software Foundation.
15  *
16  * Portals is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with Portals; if not, write to the Free Software
23  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26 /* This is a striped down version of pinger. It follows a single
27  * request-response protocol. Doesn't do Bulk data pinging. Also doesn't 
28  * send multiple packets in a single ioctl.
29  */
30
31 #define DEBUG_SUBSYSTEM S_PINGER
32
33 #include <linux/kp30.h>
34 #include <portals/p30.h>
35 #include "ping.h"
36
37 #include <linux/module.h>
38 #include <linux/proc_fs.h>
39 #include <linux/init.h>
40 #include <linux/kernel.h>
41 #include <linux/sched.h>
42 #include <linux/version.h>
43 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
44 #include <linux/workqueue.h>
45 #else
46 #include <linux/tqueue.h>
47 #endif
48 #include <linux/wait.h>
49 #include <linux/smp_lock.h>
50
51 #include <asm/unistd.h>
52 #include <asm/semaphore.h>
53
54 #define STDSIZE (sizeof(int) + sizeof(int) + 4)
55
56 static int nal  = 0;                            // Your NAL,
57 static unsigned long packets_valid = 0;         // Valid packets 
58 static int running = 1;
59 atomic_t pkt;
60        
61 static struct pingsrv_data *server=NULL;             // Our ping server
62
63 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
64 #endif
65
66 static void *pingsrv_shutdown(int err)
67 {
68         int rc;
69
70         /* Yes, we are intentionally allowing us to fall through each
71          * case in to the next.  This allows us to pass an error
72          * code to just clean up the right stuff.
73          */
74         switch (err) {
75                 case 1:
76                         /* Unlink any memory descriptors we may have used */
77                         if ((rc = PtlMDUnlink (server->mdin_h)))
78                                 PDEBUG ("PtlMDUnlink (out head buffer)", rc);
79                 case 2:
80                         /* Free the event queue */
81                         if ((rc = PtlEQFree (server->eq)))
82                                 PDEBUG ("PtlEQFree", rc);
83
84                         /* Unlink the client portal from the ME list */
85                         if ((rc = PtlMEUnlink (server->me)))
86                                         PDEBUG ("PtlMEUnlink", rc);
87
88                 case 3:
89                         kportal_put_ni (nal);
90
91                 case 4:
92                         
93                         if (server->in_buf != NULL)
94                                 PORTAL_FREE (server->in_buf, STDSIZE);
95                         
96                         if (server != NULL)
97                                 PORTAL_FREE (server, 
98                                              sizeof (struct pingsrv_data));
99                         
100         }
101
102         CDEBUG (D_OTHER, "ping sever resources released\n");
103         return NULL;
104 } /* pingsrv_shutdown() */
105
106
107 int pingsrv_thread(void *arg)
108 {
109         int rc;
110         
111         kportal_daemonize ("pingsrv");
112         server->tsk = current;
113         
114         while (running) {
115                 set_current_state (TASK_INTERRUPTIBLE);
116                 if (atomic_read (&pkt) == 0) {
117                         schedule_timeout (MAX_SCHEDULE_TIMEOUT);
118                         continue;
119                 }
120                                
121                 server->mdout.start     = server->in_buf;
122                 server->mdout.length    = STDSIZE;
123                 server->mdout.threshold = 1; 
124                 server->mdout.options   = PTL_MD_OP_PUT;
125                 server->mdout.user_ptr  = NULL;
126                 server->mdout.eventq    = PTL_EQ_NONE;
127        
128                 /* Bind the outgoing buffer */
129                 if ((rc = PtlMDBind (server->ni, server->mdout, 
130                                                 &server->mdout_h))) {
131                          PDEBUG ("PtlMDBind", rc);
132                          pingsrv_shutdown (1);
133                          return 1;
134                 }
135          
136                 
137                 server->mdin.start     = server->in_buf;
138                 server->mdin.length    = STDSIZE;
139                 server->mdin.threshold = 1; 
140                 server->mdin.options   = PTL_MD_OP_PUT;
141                 server->mdin.user_ptr  = NULL;
142                 server->mdin.eventq    = server->eq;
143         
144                 if ((rc = PtlMDAttach (server->me, server->mdin,
145                         PTL_UNLINK, &server->mdin_h))) {
146                         PDEBUG ("PtlMDAttach (bulk)", rc);
147                         CDEBUG (D_OTHER, "ping server resources allocated\n");
148                 }
149                 
150                 if ((rc = PtlPut (server->mdout_h, PTL_NOACK_REQ,
151                          server->evnt.initiator, PTL_PING_CLIENT, 0, 0, 0, 0)))
152                          PDEBUG ("PtlPut", rc);
153                 
154                 atomic_dec (&pkt);
155                 
156         }
157         pingsrv_shutdown (1);
158         running = 1;
159         return 0;    
160 }
161
162 static int pingsrv_packet(ptl_event_t *ev)
163 {
164         atomic_inc (&pkt);
165         wake_up_process (server->tsk);
166         return 1;
167 } /* pingsrv_head() */
168
169 static int pingsrv_callback(ptl_event_t *ev)
170 {
171         
172         if (ev == NULL) {
173                 CERROR ("null in callback, ev=%p\n", ev);
174                 return 0;
175         }
176         server->evnt = *ev;
177         
178         printk ("Lustre: received ping from nid "LPX64" "
179                "(off=%u rlen=%u mlen=%u head=%x)\n",
180                ev->initiator.nid, ev->offset, ev->rlength, ev->mlength,
181                *((int *)(ev->mem_desc.start + ev->offset)));
182         
183         packets_valid++;
184
185         return pingsrv_packet(ev);
186         
187 } /* pingsrv_callback() */
188
189
190 static struct pingsrv_data *pingsrv_setup(void)
191 {
192         ptl_handle_ni_t *nip;
193         int rc;
194
195        /* Aquire and initialize the proper nal for portals. */
196         if ((nip = kportal_get_ni (nal)) == NULL) {
197                 CDEBUG (D_OTHER, "Nal %d not loaded.\n", nal);
198                 return pingsrv_shutdown (4);
199         }
200
201         server->ni= *nip;
202
203         /* Based on the initialization aquire our unique portal ID. */
204         if ((rc = PtlGetId (server->ni, &server->my_id))) {
205                 PDEBUG ("PtlGetId", rc);
206                 return pingsrv_shutdown (2);
207         }
208
209         server->id_local.nid = PTL_NID_ANY;
210         server->id_local.pid = PTL_PID_ANY;
211
212         /* Attach a match entries for header packets */
213         if ((rc = PtlMEAttach (server->ni, PTL_PING_SERVER,
214             server->id_local,0, ~0,
215             PTL_RETAIN, PTL_INS_AFTER, &server->me))) {
216                 PDEBUG ("PtlMEAttach", rc);
217                 return pingsrv_shutdown (2);
218         }
219
220
221         if ((rc = PtlEQAlloc (server->ni, 64, pingsrv_callback,
222                                         &server->eq))) {
223                 PDEBUG ("PtlEQAlloc (callback)", rc);
224                 return pingsrv_shutdown (2);
225         }
226         
227         PORTAL_ALLOC (server->in_buf, STDSIZE);
228         if(!server->in_buf){
229                 CDEBUG (D_OTHER,"Allocation error\n");
230                 return pingsrv_shutdown(2);
231         }
232         
233         /* Setup the incoming buffer */
234         server->mdin.start     = server->in_buf;
235         server->mdin.length    = STDSIZE;
236         server->mdin.threshold = 1; 
237         server->mdin.options   = PTL_MD_OP_PUT;
238         server->mdin.user_ptr  = NULL;
239         server->mdin.eventq    = server->eq;
240         memset (server->in_buf, 0, STDSIZE);
241         
242         if ((rc = PtlMDAttach (server->me, server->mdin,
243                 PTL_UNLINK, &server->mdin_h))) {
244                     PDEBUG ("PtlMDAttach (bulk)", rc);
245                 CDEBUG (D_OTHER, "ping server resources allocated\n");
246        }
247  
248         /* Success! */
249         return server; 
250 } /* pingsrv_setup() */
251
252 static int pingsrv_start(void)
253 {
254         /* Setup our server */
255         if (!pingsrv_setup()) {
256                 CDEBUG (D_OTHER, "pingsrv_setup() failed, server stopped\n");
257                 return -ENOMEM;
258         }
259         kernel_thread (pingsrv_thread,NULL,0);
260         return 0;
261 } /* pingsrv_start() */
262
263
264
265 static int __init pingsrv_init(void)
266 {
267         PORTAL_ALLOC (server, sizeof(struct pingsrv_data));  
268         return pingsrv_start ();
269 } /* pingsrv_init() */
270
271
272 static void /*__exit*/ pingsrv_cleanup(void)
273 {
274         remove_proc_entry ("net/pingsrv", NULL);
275         
276         running = 0;
277         wake_up_process (server->tsk);
278         while (running != 1) {
279                 set_current_state (TASK_UNINTERRUPTIBLE);
280                 schedule_timeout (HZ);
281         }
282         
283 } /* pingsrv_cleanup() */
284
285
286 MODULE_PARM(nal, "i");
287 MODULE_PARM_DESC(nal, "Use the specified NAL "
288                 "(6-kscimacnal, 2-ksocknal, 1-kqswnal)");
289  
290 MODULE_AUTHOR("Brian Behlendorf (LLNL)");
291 MODULE_DESCRIPTION("A kernel space ping server for portals testing");
292 MODULE_LICENSE("GPL");
293
294 module_init(pingsrv_init);
295 module_exit(pingsrv_cleanup);