Whamcloud - gitweb
invoking section 3 of the GNU LGPL, to instead apply the terms of the GPL
[fs/lustre-release.git] / lnet / ulnds / procapi.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (c) 2002 Cray 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 /* api.c:
23  *  This file provides the 'api' side for the process-based nals.
24  *  it is responsible for creating the 'library' side thread,
25  *  and passing wrapped portals transactions to it.
26  *
27  *  Along with initialization, shutdown, and transport to the library
28  *  side, this file contains some stubs to satisfy the nal definition.
29  */
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <syscall.h>
35 #include <procbridge.h>
36 #include <pqtimer.h>
37 #include <dispatch.h>
38 #include <errno.h>
39
40
41 /* Function: forward
42  * Arguments: nal_t *nal: pointer to my top-side nal structure
43  *            id: the command to pass to the lower layer
44  *            args, args_len:pointer to and length of the request
45  *            ret, ret_len:  pointer to and size of the result
46  * Returns: a portals status code
47  *
48  * forwards a packaged api call from the 'api' side to the 'library'
49  *   side, and collects the result
50  */
51 #define forward_failure(operand,fd,buffer,length)\
52        if(syscall(SYS_##operand,fd,buffer,length)!=length){\
53           lib_fini(b->nal_cb);\
54           return(PTL_SEGV);\
55        }
56 static int procbridge_forward(nal_t *n, int id, void *args, ptl_size_t args_len,
57                               void *ret, ptl_size_t ret_len)
58 {
59     bridge b=(bridge)n->nal_data;
60     procbridge p=(procbridge)b->local;
61     int lib=p->to_lib[1];
62     int k;
63
64     forward_failure(write,lib, &id, sizeof(id));
65     forward_failure(write,lib,&args_len, sizeof(args_len));
66     forward_failure(write,lib,&ret_len, sizeof(ret_len));
67     forward_failure(write,lib,args, args_len);
68
69     do {
70         k=syscall(SYS_read, p->from_lib[0], ret, ret_len);
71     } while ((k!=ret_len) && (errno += EINTR));
72
73     if(k!=ret_len){
74         perror("nal: read return block");
75         return PTL_SEGV;
76     }
77     return (PTL_OK);
78 }
79 #undef forward_failure
80
81
82 /* Function: shutdown
83  * Arguments: nal: a pointer to my top side nal structure
84  *            ni: my network interface index
85  *
86  * cleanup nal state, reclaim the lower side thread and
87  *   its state using PTL_FINI codepoint
88  */
89 static int procbridge_shutdown(nal_t *n, int ni)
90 {
91     bridge b=(bridge)n->nal_data;
92     procbridge p=(procbridge)b->local;
93     int code=PTL_FINI;
94
95     syscall(SYS_write, p->to_lib[1],&code,sizeof(code));
96     syscall(SYS_read, p->from_lib[0],&code,sizeof(code));
97
98     syscall(SYS_close, p->to_lib[0]);
99     syscall(SYS_close, p->to_lib[1]);
100     syscall(SYS_close, p->from_lib[0]);
101     syscall(SYS_close, p->from_lib[1]);
102
103     free(p);
104     return(0);
105 }
106
107
108 /* Function: validate
109  *    useless stub
110  */
111 static int procbridge_validate(nal_t *nal, void *base, ptl_size_t extent)
112 {
113     return(0);
114 }
115
116
117 /* Function: yield
118  * Arguments:  pid:
119  *
120  *  this function was originally intended to allow the
121  *   lower half thread to be scheduled to allow progress. we
122  *   overload it to explicitly block until signalled by the
123  *   lower half.
124  */
125 static void procbridge_yield(nal_t *n)
126 {
127     bridge b=(bridge)n->nal_data;
128     procbridge p=(procbridge)b->local;
129
130     pthread_mutex_lock(&p->mutex);
131     pthread_cond_wait(&p->cond,&p->mutex);
132     pthread_mutex_unlock(&p->mutex);
133 }
134
135
136 static void procbridge_lock(nal_t * nal, unsigned long *flags){}
137 static void procbridge_unlock(nal_t * nal, unsigned long *flags){}
138 /* api_nal
139  *  the interface vector to allow the generic code to access
140  *  this nal. this is seperate from the library side nal_cb.
141  *  TODO: should be dyanmically allocated
142  */
143 static nal_t api_nal = {
144     ni:       {0},
145     nal_data: NULL,
146     forward:  procbridge_forward,
147     shutdown: procbridge_shutdown,
148     validate: procbridge_validate,
149     yield:    procbridge_yield,
150     lock:     procbridge_lock,
151     unlock:   procbridge_unlock
152 };
153
154 /* Function: bridge_init
155  *
156  * Arguments:  pid: requested process id (port offset)
157  *                  PTL_ID_ANY not supported.
158  *             desired: limits passed from the application
159  *                      and effectively ignored
160  *             actual:  limits actually allocated and returned
161  *
162  * Returns: a pointer to my statically allocated top side NAL
163  *          structure
164  *
165  * initializes the tcp nal. we define unix_failure as an
166  * error wrapper to cut down clutter.
167  */
168 #define unix_failure(operand,fd,buffer,length,text)\
169        if(syscall(SYS_##operand,fd,buffer,length)!=length){\
170           perror(text);\
171           return(NULL);\
172        }
173 #if 0
174 static nal_t *bridge_init(ptl_interface_t nal,
175                           ptl_pid_t pid_request,
176                           ptl_ni_limits_t *desired,
177                           ptl_ni_limits_t *actual,
178                           int *rc)
179 {
180     procbridge p;
181     bridge b;
182     static int initialized=0;
183     ptl_ni_limits_t limits = {-1,-1,-1,-1,-1};
184
185     if(initialized) return (&api_nal);
186
187     init_unix_timer();
188
189     b=(bridge)malloc(sizeof(struct bridge));
190     p=(procbridge)malloc(sizeof(struct procbridge));
191     api_nal.nal_data=b;
192     b->local=p;
193
194     if(pipe(p->to_lib) || pipe(p->from_lib)) {
195         perror("nal_init: pipe");
196         return(NULL);
197     }
198
199     if (desired) limits = *desired;
200     unix_failure(write,p->to_lib[1], &pid_request, sizeof(pid_request),
201                        "nal_init: write");
202     unix_failure(write,p->to_lib[1], &limits, sizeof(ptl_ni_limits_t),
203                        "nal_init: write");
204     unix_failure(write,p->to_lib[1], &nal, sizeof(ptl_interface_t),
205                        "nal_init: write");
206
207     if(pthread_create(&p->t, NULL, nal_thread, b)) {
208         perror("nal_init: pthread_create");
209         return(NULL);
210     }
211
212     unix_failure(read,p->from_lib[0], actual, sizeof(ptl_ni_limits_t),
213                  "tcp_init: read");
214     unix_failure(read,p->from_lib[0], rc, sizeof(rc),
215                  "nal_init: read");
216
217     if(*rc) return(NULL);
218
219     initialized = 1;
220     pthread_mutex_init(&p->mutex,0);
221     pthread_cond_init(&p->cond, 0);
222
223     return (&api_nal);
224 }
225 #endif
226
227 ptl_nid_t tcpnal_mynid;
228
229 nal_t *procbridge_interface(int num_interface,
230                             ptl_pt_index_t ptl_size,
231                             ptl_ac_index_t acl_size,
232                             ptl_pid_t requested_pid)
233 {
234     procbridge p;
235     bridge b;
236     static int initialized=0;
237     ptl_ni_limits_t limits = {-1,-1,-1,-1,-1};
238     int rc, nal_type = PTL_IFACE_TCP;/* PTL_IFACE_DEFAULT FIXME hack */
239
240     if(initialized) return (&api_nal);
241
242     init_unix_timer();
243
244     b=(bridge)malloc(sizeof(struct bridge));
245     p=(procbridge)malloc(sizeof(struct procbridge));
246     api_nal.nal_data=b;
247     b->local=p;
248
249     if(pipe(p->to_lib) || pipe(p->from_lib)) {
250         perror("nal_init: pipe");
251         return(NULL);
252     }
253
254     if (ptl_size)
255             limits.max_ptable_index = ptl_size;
256     if (acl_size)
257             limits.max_atable_index = acl_size;
258
259     unix_failure(write,p->to_lib[1], &requested_pid, sizeof(requested_pid),
260                        "nal_init: write");
261     unix_failure(write,p->to_lib[1], &limits, sizeof(ptl_ni_limits_t),
262                        "nal_init: write");
263     unix_failure(write,p->to_lib[1], &nal_type, sizeof(nal_type),
264                        "nal_init: write");
265
266     if(pthread_create(&p->t, NULL, nal_thread, b)) {
267         perror("nal_init: pthread_create");
268         return(NULL);
269     }
270
271     unix_failure(read,p->from_lib[0], &rc, sizeof(rc),
272                  "nal_init: read");
273
274     if(rc) return(NULL);
275
276     b->nal_cb->ni.nid = tcpnal_mynid;
277     initialized = 1;
278     pthread_mutex_init(&p->mutex,0);
279     pthread_cond_init(&p->cond, 0);
280
281     return (&api_nal);
282 }
283 #undef unix_failure