Whamcloud - gitweb
* landed unified portals (b_hd_cleanup_merge_singleportals) on HEAD
[fs/lustre-release.git] / lustre / portals / unals / 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  *  Copyright (c) 2003 Cluster File Systems, Inc.
6  *
7  *   This file is part of Lustre, http://www.lustre.org.
8  *
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.
12  *
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.
17  *
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.
21  */
22
23 /* api.c:
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.
27  *
28  *  Along with initialization, shutdown, and transport to the library
29  *  side, this file contains some stubs to satisfy the nal definition.
30  */
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <string.h>
35 #ifndef __CYGWIN__
36 #include <syscall.h>
37 #endif
38 #include <sys/socket.h>
39 #include <procbridge.h>
40 #include <pqtimer.h>
41 #include <dispatch.h>
42 #include <errno.h>
43
44
45 /* XXX CFS workaround, to give a chance to let nal thread wake up
46  * from waiting in select
47  */
48 static int procbridge_notifier_handler(void *arg)
49 {
50     static char buf[8];
51     procbridge p = (procbridge) arg;
52
53     syscall(SYS_read, p->notifier[1], buf, sizeof(buf));
54     return 1;
55 }
56
57 void procbridge_wakeup_nal(procbridge p)
58 {
59     static char buf[8];
60     syscall(SYS_write, p->notifier[0], buf, sizeof(buf));
61 }
62
63 /* Function: shutdown
64  * Arguments: nal: a pointer to my top side nal structure
65  *            ni: my network interface index
66  *
67  * cleanup nal state, reclaim the lower side thread and
68  *   its state using PTL_FINI codepoint
69  */
70 static void procbridge_shutdown(nal_t *n)
71 {
72     lib_nal_t *nal = n->nal_data;
73     bridge b=(bridge)nal->libnal_data;
74     procbridge p=(procbridge)b->local;
75
76     p->nal_flags |= NAL_FLAG_STOPPING;
77     procbridge_wakeup_nal(p);
78
79     do {
80         pthread_mutex_lock(&p->mutex);
81         if (p->nal_flags & NAL_FLAG_STOPPED) {
82                 pthread_mutex_unlock(&p->mutex);
83                 break;
84         }
85         pthread_cond_wait(&p->cond, &p->mutex);
86         pthread_mutex_unlock(&p->mutex);
87     } while (1);
88
89     free(p);
90 }
91
92
93 /* forward decl */
94 extern int procbridge_startup (nal_t *, ptl_pid_t,
95                                ptl_ni_limits_t *, ptl_ni_limits_t *);
96
97 /* api_nal
98  *  the interface vector to allow the generic code to access
99  *  this nal. this is seperate from the library side lib_nal.
100  *  TODO: should be dyanmically allocated
101  */
102 nal_t procapi_nal = {
103     nal_data: NULL,
104     nal_ni_init: procbridge_startup,
105     nal_ni_fini: procbridge_shutdown,
106 };
107
108 ptl_nid_t tcpnal_mynid;
109
110 #ifdef ENABLE_SELECT_DISPATCH
111 procbridge __global_procbridge = NULL;
112 #endif
113
114 /* Function: procbridge_startup
115  *
116  * Arguments:  pid: requested process id (port offset)
117  *                  PTL_ID_ANY not supported.
118  *             desired: limits passed from the application
119  *                      and effectively ignored
120  *             actual:  limits actually allocated and returned
121  *
122  * Returns: portals rc
123  *
124  * initializes the tcp nal. we define unix_failure as an
125  * error wrapper to cut down clutter.
126  */
127 int procbridge_startup (nal_t *nal, ptl_pid_t requested_pid,
128                         ptl_ni_limits_t *requested_limits,
129                         ptl_ni_limits_t *actual_limits)
130 {
131     nal_init_args_t args;
132
133     procbridge p;
134     bridge b;
135     /* XXX nal_type is purely private to tcpnal here */
136     int nal_type = PTL_IFACE_TCP;/* PTL_IFACE_DEFAULT FIXME hack */
137
138     LASSERT(nal == &procapi_nal);
139
140     init_unix_timer();
141
142     b=(bridge)malloc(sizeof(struct bridge));
143     p=(procbridge)malloc(sizeof(struct procbridge));
144     b->local=p;
145
146     args.nia_requested_pid = requested_pid;
147     args.nia_requested_limits = requested_limits;
148     args.nia_actual_limits = actual_limits;
149     args.nia_nal_type = nal_type;
150     args.nia_bridge = b;
151     args.nia_apinal = nal;
152
153     /* init procbridge */
154     pthread_mutex_init(&p->mutex,0);
155     pthread_cond_init(&p->cond, 0);
156     p->nal_flags = 0;
157
158     /* initialize notifier */
159     if (socketpair(AF_UNIX, SOCK_STREAM, 0, p->notifier)) {
160         perror("socketpair failed");
161         return PTL_FAIL;
162     }
163
164     if (!register_io_handler(p->notifier[1], READ_HANDLER,
165                 procbridge_notifier_handler, p)) {
166         perror("fail to register notifier handler");
167         return PTL_FAIL;
168     }
169
170 #ifdef ENABLE_SELECT_DISPATCH
171     __global_procbridge = p;
172 #endif
173
174     /* create nal thread */
175     if (pthread_create(&p->t, NULL, nal_thread, &args)) {
176         perror("nal_init: pthread_create");
177         return PTL_FAIL;
178     }
179
180     do {
181         pthread_mutex_lock(&p->mutex);
182         if (p->nal_flags & (NAL_FLAG_RUNNING | NAL_FLAG_STOPPED)) {
183                 pthread_mutex_unlock(&p->mutex);
184                 break;
185         }
186         pthread_cond_wait(&p->cond, &p->mutex);
187         pthread_mutex_unlock(&p->mutex);
188     } while (1);
189
190     if (p->nal_flags & NAL_FLAG_STOPPED)
191         return PTL_FAIL;
192
193     b->lib_nal->libnal_ni.ni_pid.nid = tcpnal_mynid;
194
195     return PTL_OK;
196 }