Whamcloud - gitweb
b=5498
[fs/lustre-release.git] / lnet / ulnds / socklnd / 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 <netdb.h>
39 #include <sys/socket.h>
40 #include <netinet/in.h>
41 #include <procbridge.h>
42 #include <pqtimer.h>
43 #include <dispatch.h>
44 #include <errno.h>
45 #ifdef HAVE_GETHOSTBYNAME
46 # include <sys/utsname.h>
47 #endif
48
49 #if !HAVE_LIBPTHREAD
50 # error "This LND requires a multi-threaded runtime"
51 #endif
52
53 /* XXX CFS workaround, to give a chance to let nal thread wake up
54  * from waiting in select
55  */
56 static int procbridge_notifier_handler(void *arg)
57 {
58     static char buf[8];
59     procbridge p = (procbridge) arg;
60
61     syscall(SYS_read, p->notifier[1], buf, sizeof(buf));
62     return 1;
63 }
64
65 void procbridge_wakeup_nal(procbridge p)
66 {
67     static char buf[8];
68     syscall(SYS_write, p->notifier[0], buf, sizeof(buf));
69 }
70
71 lnd_t the_tcplnd = {
72         .lnd_type      = SOCKLND,
73         .lnd_startup   = procbridge_startup,
74         .lnd_shutdown  = procbridge_shutdown,
75         .lnd_send      = tcpnal_send,
76         .lnd_recv      = tcpnal_recv,
77         .lnd_notify    = tcpnal_notify,
78 };
79 int       tcpnal_running;
80
81 /* Function: shutdown
82  * Arguments: ni: the instance of me
83  *
84  * cleanup nal state, reclaim the lower side thread and
85  *   its state using PTL_FINI codepoint
86  */
87 void
88 procbridge_shutdown(lnet_ni_t *ni)
89 {
90     bridge b=(bridge)ni->ni_data;
91     procbridge p=(procbridge)b->local;
92
93     p->nal_flags |= NAL_FLAG_STOPPING;
94     procbridge_wakeup_nal(p);
95
96     do {
97         pthread_mutex_lock(&p->mutex);
98         if (p->nal_flags & NAL_FLAG_STOPPED) {
99                 pthread_mutex_unlock(&p->mutex);
100                 break;
101         }
102         pthread_cond_wait(&p->cond, &p->mutex);
103         pthread_mutex_unlock(&p->mutex);
104     } while (1);
105
106     free(p);
107     tcpnal_running = 0;
108 }
109
110 #ifdef ENABLE_SELECT_DISPATCH
111 procbridge __global_procbridge = NULL;
112 #endif
113
114 /* Function: procbridge_startup
115  *
116  * Arguments:  ni:          the instance of me
117  *             interfaces:  ignored
118  *
119  * Returns: portals rc
120  *
121  * initializes the tcp nal. we define unix_failure as an
122  * error wrapper to cut down clutter.
123  */
124 int
125 procbridge_startup (lnet_ni_t *ni)
126 {
127     procbridge p;
128     bridge     b;
129     int        rc;
130
131     /* NB The local NID is not assigned.  We only ever connect to the socknal,
132      * which assigns the src nid/pid on incoming non-privileged connections
133      * (i.e. us), and we don't accept connections. */
134
135     LASSERT (ni->ni_lnd == &the_tcplnd);
136     LASSERT (!tcpnal_running);                  /* only single instance supported */
137     LASSERT (ni->ni_interfaces[0] == NULL);     /* explicit interface(s) not supported */
138
139     /* The credit settings here are pretty irrelevent.  Userspace tcplnd has no
140      * tx descriptor pool to exhaust and does a blocking send; that's the real
141      * limit on send concurrency. */
142     ni->ni_maxtxcredits = 1000;
143     ni->ni_peertxcredits = 1000;
144     
145     init_unix_timer();
146
147     b=(bridge)malloc(sizeof(struct bridge));
148     p=(procbridge)malloc(sizeof(struct procbridge));
149     b->local=p;
150     b->b_ni = ni;
151     ni->ni_data = b;
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         rc = -errno;
162         return rc;
163     }
164
165     if (!register_io_handler(p->notifier[1], READ_HANDLER,
166                 procbridge_notifier_handler, p)) {
167         perror("fail to register notifier handler");
168         return -ENOMEM;
169     }
170
171 #ifdef ENABLE_SELECT_DISPATCH
172     __global_procbridge = p;
173 #endif
174
175     /* create nal thread */
176     rc = pthread_create(&p->t, NULL, nal_thread, b);
177     if (rc != 0) {
178         perror("nal_init: pthread_create");
179         return -ESRCH;
180     }
181
182     do {
183         pthread_mutex_lock(&p->mutex);
184         if (p->nal_flags & (NAL_FLAG_RUNNING | NAL_FLAG_STOPPED)) {
185                 pthread_mutex_unlock(&p->mutex);
186                 break;
187         }
188         pthread_cond_wait(&p->cond, &p->mutex);
189         pthread_mutex_unlock(&p->mutex);
190     } while (1);
191
192     if (p->nal_flags & NAL_FLAG_STOPPED)
193         return -ENETDOWN;
194
195     tcpnal_running = 1;
196
197     return 0;
198 }