1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (c) 2002 Cray Inc.
5 * Copyright (c) 2003 Cluster File Systems, Inc.
7 * This file is part of Lustre, http://www.lustre.org.
9 * Lustre is free software; you can redistribute it and/or
10 * modify it under the terms of version 2 of the GNU General Public
11 * License as published by the Free Software Foundation.
13 * Lustre is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with Lustre; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 * This file provides the 'api' side for the process-based nals.
25 * it is responsible for creating the 'library' side thread,
26 * and passing wrapped portals transactions to it.
28 * Along with initialization, shutdown, and transport to the library
29 * side, this file contains some stubs to satisfy the nal definition.
38 #include <sys/socket.h>
39 #include <procbridge.h>
45 /* XXX CFS workaround, to give a chance to let nal thread wake up
46 * from waiting in select
48 static int procbridge_notifier_handler(void *arg)
51 procbridge p = (procbridge) arg;
53 syscall(SYS_read, p->notifier[1], buf, sizeof(buf));
57 void procbridge_wakeup_nal(procbridge p)
60 syscall(SYS_write, p->notifier[0], buf, sizeof(buf));
64 * Arguments: nal_t *nal: pointer to my top-side nal structure
65 * id: the command to pass to the lower layer
66 * args, args_len:pointer to and length of the request
67 * ret, ret_len: pointer to and size of the result
68 * Returns: a portals status code
70 * forwards a packaged api call from the 'api' side to the 'library'
71 * side, and collects the result
73 static int procbridge_forward(nal_t *n, int id, void *args, size_t args_len,
74 void *ret, size_t ret_len)
76 bridge b = (bridge) n->nal_data;
85 lib_dispatch(b->nal_cb, NULL, id, args, ret);
92 * Arguments: nal: a pointer to my top side nal structure
93 * ni: my network interface index
95 * cleanup nal state, reclaim the lower side thread and
96 * its state using PTL_FINI codepoint
98 static int procbridge_shutdown(nal_t *n, int ni)
100 bridge b=(bridge)n->nal_data;
101 procbridge p=(procbridge)b->local;
103 p->nal_flags |= NAL_FLAG_STOPPING;
104 procbridge_wakeup_nal(p);
107 pthread_mutex_lock(&p->mutex);
108 if (p->nal_flags & NAL_FLAG_STOPPED) {
109 pthread_mutex_unlock(&p->mutex);
112 pthread_cond_wait(&p->cond, &p->mutex);
113 pthread_mutex_unlock(&p->mutex);
121 /* Function: validate
124 static int procbridge_validate(nal_t *nal, void *base, size_t extent)
130 /* FIXME cfs temporary workaround! FIXME
131 * global time out value
133 int __tcpnal_eqwait_timeout_value = 0;
134 int __tcpnal_eqwait_timedout = 0;
139 * this function was originally intended to allow the
140 * lower half thread to be scheduled to allow progress. we
141 * overload it to explicitly block until signalled by the
144 static void procbridge_yield(nal_t *n)
146 bridge b=(bridge)n->nal_data;
147 procbridge p=(procbridge)b->local;
149 pthread_mutex_lock(&p->mutex);
150 if (!__tcpnal_eqwait_timeout_value) {
151 pthread_cond_wait(&p->cond,&p->mutex);
154 struct timespec timeout;
156 gettimeofday(&now, NULL);
157 timeout.tv_sec = now.tv_sec + __tcpnal_eqwait_timeout_value;
158 timeout.tv_nsec = now.tv_usec * 1000;
160 __tcpnal_eqwait_timedout =
161 pthread_cond_timedwait(&p->cond, &p->mutex, &timeout);
163 pthread_mutex_unlock(&p->mutex);
167 static void procbridge_lock(nal_t * nal, unsigned long *flags){}
168 static void procbridge_unlock(nal_t * nal, unsigned long *flags){}
170 * the interface vector to allow the generic code to access
171 * this nal. this is seperate from the library side nal_cb.
172 * TODO: should be dyanmically allocated
174 static nal_t api_nal = {
177 forward: procbridge_forward,
178 shutdown: procbridge_shutdown,
179 validate: procbridge_validate,
180 yield: procbridge_yield,
181 lock: procbridge_lock,
182 unlock: procbridge_unlock
185 ptl_nid_t tcpnal_mynid;
187 /* Function: procbridge_interface
189 * Arguments: pid: requested process id (port offset)
190 * PTL_ID_ANY not supported.
191 * desired: limits passed from the application
192 * and effectively ignored
193 * actual: limits actually allocated and returned
195 * Returns: a pointer to my statically allocated top side NAL
198 * initializes the tcp nal. we define unix_failure as an
199 * error wrapper to cut down clutter.
201 nal_t *procbridge_interface(int num_interface,
202 ptl_pt_index_t ptl_size,
203 ptl_ac_index_t acl_size,
204 ptl_pid_t requested_pid)
206 nal_init_args_t args;
209 static int initialized=0;
210 ptl_ni_limits_t limits = {-1,-1,-1,-1,-1};
211 int nal_type = PTL_IFACE_TCP;/* PTL_IFACE_DEFAULT FIXME hack */
213 if(initialized) return (&api_nal);
217 b=(bridge)malloc(sizeof(struct bridge));
218 p=(procbridge)malloc(sizeof(struct procbridge));
223 limits.max_ptable_index = ptl_size;
225 limits.max_atable_index = acl_size;
227 args.nia_requested_pid = requested_pid;
228 args.nia_limits = &limits;
229 args.nia_nal_type = nal_type;
232 /* init procbridge */
233 pthread_mutex_init(&p->mutex,0);
234 pthread_cond_init(&p->cond, 0);
236 pthread_mutex_init(&p->nal_cb_lock, 0);
238 /* initialize notifier */
239 if (socketpair(AF_UNIX, SOCK_STREAM, 0, p->notifier)) {
240 perror("socketpair failed");
244 if (!register_io_handler(p->notifier[1], READ_HANDLER,
245 procbridge_notifier_handler, p)) {
246 perror("fail to register notifier handler");
250 /* create nal thread */
251 if (pthread_create(&p->t, NULL, nal_thread, &args)) {
252 perror("nal_init: pthread_create");
257 pthread_mutex_lock(&p->mutex);
258 if (p->nal_flags & (NAL_FLAG_RUNNING | NAL_FLAG_STOPPED)) {
259 pthread_mutex_unlock(&p->mutex);
262 pthread_cond_wait(&p->cond, &p->mutex);
263 pthread_mutex_unlock(&p->mutex);
266 if (p->nal_flags & NAL_FLAG_STOPPED)
269 b->nal_cb->ni.nid = tcpnal_mynid;