| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: rumpuser_sp.c,v 1.1 2010/10/27 20:44:50 pooka Exp $ */ | | 1 | /* $NetBSD: rumpuser_sp.c,v 1.2 2010/10/28 14:37:29 pooka Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2010 Antti Kantee. All Rights Reserved. | | 4 | * Copyright (c) 2010 Antti Kantee. All Rights Reserved. |
5 | * | | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | | 7 | * modification, are permitted provided that the following conditions |
8 | * are met: | | 8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright | | 9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | | 10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright | | 11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the | | 12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. | | 13 | * documentation and/or other materials provided with the distribution. |
14 | * | | 14 | * |
| @@ -28,27 +28,27 @@ | | | @@ -28,27 +28,27 @@ |
28 | /* | | 28 | /* |
29 | * Sysproxy routines. This provides system RPC support over host sockets. | | 29 | * Sysproxy routines. This provides system RPC support over host sockets. |
30 | * The most notable limitation is that the client and server must share | | 30 | * The most notable limitation is that the client and server must share |
31 | * the same ABI. This does not mean that they have to be the same | | 31 | * the same ABI. This does not mean that they have to be the same |
32 | * machine or that they need to run the same version of the host OS, | | 32 | * machine or that they need to run the same version of the host OS, |
33 | * just that they must agree on the data structures. This even *might* | | 33 | * just that they must agree on the data structures. This even *might* |
34 | * work correctly from one hardware architecture to another. | | 34 | * work correctly from one hardware architecture to another. |
35 | * | | 35 | * |
36 | * Not finished yet, i.e. don't use in production. Lacks locking plus | | 36 | * Not finished yet, i.e. don't use in production. Lacks locking plus |
37 | * handling of multiple clients and unexpected connection closes. | | 37 | * handling of multiple clients and unexpected connection closes. |
38 | */ | | 38 | */ |
39 | | | 39 | |
40 | #include <sys/cdefs.h> | | 40 | #include <sys/cdefs.h> |
41 | __RCSID("$NetBSD: rumpuser_sp.c,v 1.1 2010/10/27 20:44:50 pooka Exp $"); | | 41 | __RCSID("$NetBSD: rumpuser_sp.c,v 1.2 2010/10/28 14:37:29 pooka Exp $"); |
42 | | | 42 | |
43 | #include <sys/types.h> | | 43 | #include <sys/types.h> |
44 | #include <sys/mman.h> | | 44 | #include <sys/mman.h> |
45 | #include <sys/socket.h> | | 45 | #include <sys/socket.h> |
46 | | | 46 | |
47 | #include <arpa/inet.h> | | 47 | #include <arpa/inet.h> |
48 | #include <netinet/in.h> | | 48 | #include <netinet/in.h> |
49 | #include <netinet/tcp.h> | | 49 | #include <netinet/tcp.h> |
50 | | | 50 | |
51 | #include <assert.h> | | 51 | #include <assert.h> |
52 | #include <errno.h> | | 52 | #include <errno.h> |
53 | #include <fcntl.h> | | 53 | #include <fcntl.h> |
54 | #include <poll.h> | | 54 | #include <poll.h> |
| @@ -111,26 +111,27 @@ struct rsp_copydata { | | | @@ -111,26 +111,27 @@ struct rsp_copydata { |
111 | void *rcp_addr; | | 111 | void *rcp_addr; |
112 | uint8_t rcp_data[0]; | | 112 | uint8_t rcp_data[0]; |
113 | }; | | 113 | }; |
114 | | | 114 | |
115 | /* syscall response */ | | 115 | /* syscall response */ |
116 | struct rsp_sysresp { | | 116 | struct rsp_sysresp { |
117 | int rsys_error; | | 117 | int rsys_error; |
118 | register_t rsys_retval[2]; | | 118 | register_t rsys_retval[2]; |
119 | }; | | 119 | }; |
120 | | | 120 | |
121 | | | 121 | |
122 | struct spclient { | | 122 | struct spclient { |
123 | int spc_fd; | | 123 | int spc_fd; |
| | | 124 | struct lwp *spc_lwp; |
124 | | | 125 | |
125 | /* incoming */ | | 126 | /* incoming */ |
126 | struct rsp_hdr spc_hdr; | | 127 | struct rsp_hdr spc_hdr; |
127 | uint8_t *spc_buf; | | 128 | uint8_t *spc_buf; |
128 | size_t spc_off; | | 129 | size_t spc_off; |
129 | | | 130 | |
130 | #if 0 | | 131 | #if 0 |
131 | /* outgoing */ | | 132 | /* outgoing */ |
132 | int spc_obusy; | | 133 | int spc_obusy; |
133 | pthread_mutex_t spc_omtx; | | 134 | pthread_mutex_t spc_omtx; |
134 | pthread_cond_t spc_cv; | | 135 | pthread_cond_t spc_cv; |
135 | #endif | | 136 | #endif |
136 | }; | | 137 | }; |
| @@ -302,33 +303,36 @@ send_anonmmap_resp(struct spclient *spc, | | | @@ -302,33 +303,36 @@ send_anonmmap_resp(struct spclient *spc, |
302 | | | 303 | |
303 | rhdr.rsp_len = sizeof(rhdr) + sizeof(addr); | | 304 | rhdr.rsp_len = sizeof(rhdr) + sizeof(addr); |
304 | rhdr.rsp_reqno = reqno; | | 305 | rhdr.rsp_reqno = reqno; |
305 | rhdr.rsp_type = RUMPSP_ANONMMAP_RESP; | | 306 | rhdr.rsp_type = RUMPSP_ANONMMAP_RESP; |
306 | rhdr.rsp_sysnum = 0; | | 307 | rhdr.rsp_sysnum = 0; |
307 | | | 308 | |
308 | dosend(spc, &rhdr, sizeof(rhdr)); | | 309 | dosend(spc, &rhdr, sizeof(rhdr)); |
309 | dosend(spc, &addr, sizeof(addr)); | | 310 | dosend(spc, &addr, sizeof(addr)); |
310 | | | 311 | |
311 | return 0; | | 312 | return 0; |
312 | } | | 313 | } |
313 | | | 314 | |
314 | static void | | 315 | static void |
315 | serv_handle_disco(unsigned int idx) | | 316 | serv_handledisco(unsigned int idx) |
316 | { | | 317 | { |
317 | struct spclient *spc = &spclist[idx]; | | 318 | struct spclient *spc = &spclist[idx]; |
318 | int fd = spc->spc_fd; | | 319 | int fd = spc->spc_fd; |
319 | | | 320 | |
320 | DPRINTF(("rump_sp: disconnecting [%u]\n", idx)); | | 321 | DPRINTF(("rump_sp: disconnecting [%u]\n", idx)); |
321 | | | 322 | |
| | | 323 | rump_pub_lwproc_switch(spc->spc_lwp); |
| | | 324 | rump_pub_lwproc_releaselwp(); |
| | | 325 | |
322 | free(spc->spc_buf); | | 326 | free(spc->spc_buf); |
323 | memset(spc, 0, sizeof(*spc)); | | 327 | memset(spc, 0, sizeof(*spc)); |
324 | close(fd); | | 328 | close(fd); |
325 | pfdlist[idx].fd = -1; | | 329 | pfdlist[idx].fd = -1; |
326 | nfds--; | | 330 | nfds--; |
327 | | | 331 | |
328 | if (idx == maxidx) { | | 332 | if (idx == maxidx) { |
329 | while (idx--) { | | 333 | while (idx--) { |
330 | if (pfdlist[idx].fd != -1) { | | 334 | if (pfdlist[idx].fd != -1) { |
331 | maxidx = idx; | | 335 | maxidx = idx; |
332 | break; | | 336 | break; |
333 | } | | 337 | } |
334 | assert(idx != 0); | | 338 | assert(idx != 0); |
| @@ -359,57 +363,68 @@ serv_handleconn(int fd, connecthook_fn c | | | @@ -359,57 +363,68 @@ serv_handleconn(int fd, connecthook_fn c |
359 | | | 363 | |
360 | flags = fcntl(newfd, F_GETFL, 0); | | 364 | flags = fcntl(newfd, F_GETFL, 0); |
361 | if (fcntl(newfd, F_SETFL, flags | O_NONBLOCK) == -1) { | | 365 | if (fcntl(newfd, F_SETFL, flags | O_NONBLOCK) == -1) { |
362 | close(newfd); | | 366 | close(newfd); |
363 | return errno; | | 367 | return errno; |
364 | } | | 368 | } |
365 | flags = 1; | | 369 | flags = 1; |
366 | | | 370 | |
367 | if ((error = connhook(newfd)) != 0) { | | 371 | if ((error = connhook(newfd)) != 0) { |
368 | close(newfd); | | 372 | close(newfd); |
369 | return error; | | 373 | return error; |
370 | } | | 374 | } |
371 | | | 375 | |
| | | 376 | if ((error = rump_pub_lwproc_newproc()) != 0) { |
| | | 377 | close(newfd); |
| | | 378 | return error; |
| | | 379 | } |
| | | 380 | |
372 | /* find empty slot the simple way */ | | 381 | /* find empty slot the simple way */ |
373 | for (i = 0; i < MAXCLI; i++) { | | 382 | for (i = 0; i < MAXCLI; i++) { |
374 | if (pfdlist[i].fd == -1) | | 383 | if (pfdlist[i].fd == -1) |
375 | break; | | 384 | break; |
376 | } | | 385 | } |
377 | | | 386 | |
378 | assert(i < MAXCLI); | | 387 | assert(i < MAXCLI); |
379 | nfds++; | | 388 | nfds++; |
380 | | | 389 | |
381 | pfdlist[i].fd = newfd; | | 390 | pfdlist[i].fd = newfd; |
382 | spclist[i].spc_fd = newfd; | | 391 | spclist[i].spc_fd = newfd; |
| | | 392 | spclist[i].spc_lwp = rump_pub_lwproc_curlwp(); |
383 | if (maxidx < i) | | 393 | if (maxidx < i) |
384 | maxidx = i; | | 394 | maxidx = i; |
385 | | | 395 | |
386 | DPRINTF(("rump_sp: added new connection at idx %u\n", i)); | | 396 | DPRINTF(("rump_sp: added new connection at idx %u, pid %d\n", |
| | | 397 | i, rump_sys_getpid())); |
| | | 398 | |
| | | 399 | rump_pub_lwproc_switch(NULL); |
387 | | | 400 | |
388 | return 0; | | 401 | return 0; |
389 | } | | 402 | } |
390 | | | 403 | |
391 | static void | | 404 | static void |
392 | serv_handlesyscall(struct spclient *spc, struct rsp_hdr *rhdr, uint8_t *data) | | 405 | serv_handlesyscall(struct spclient *spc, struct rsp_hdr *rhdr, uint8_t *data) |
393 | { | | 406 | { |
394 | register_t retval[2]; | | 407 | register_t retval[2]; |
395 | int rv, sysnum; | | 408 | int rv, sysnum; |
396 | | | 409 | |
397 | sysnum = (int)rhdr->rsp_sysnum; | | 410 | sysnum = (int)rhdr->rsp_sysnum; |
398 | DPRINTF(("rump_sp: handling syscall %d from client %d\n", | | 411 | DPRINTF(("rump_sp: handling syscall %d from client %d\n", |
399 | sysnum, 0)); | | 412 | sysnum, 0)); |
400 | | | 413 | |
401 | pthread_setspecific(spclient_tls, spc); | | 414 | pthread_setspecific(spclient_tls, spc); |
| | | 415 | rump_pub_lwproc_switch(spc->spc_lwp); |
402 | rv = rump_pub_syscall(sysnum, data, retval); | | 416 | rv = rump_pub_syscall(sysnum, data, retval); |
| | | 417 | rump_pub_lwproc_switch(NULL); |
403 | pthread_setspecific(spclient_tls, NULL); | | 418 | pthread_setspecific(spclient_tls, NULL); |
404 | | | 419 | |
405 | send_syscall_resp(spc, rhdr->rsp_reqno, rv, retval); | | 420 | send_syscall_resp(spc, rhdr->rsp_reqno, rv, retval); |
406 | } | | 421 | } |
407 | | | 422 | |
408 | static int | | 423 | static int |
409 | readframe(struct spclient *spc) | | 424 | readframe(struct spclient *spc) |
410 | { | | 425 | { |
411 | int fd = spc->spc_fd; | | 426 | int fd = spc->spc_fd; |
412 | size_t left; | | 427 | size_t left; |
413 | size_t framelen; | | 428 | size_t framelen; |
414 | ssize_t n; | | 429 | ssize_t n; |
415 | | | 430 | |
| @@ -802,27 +817,27 @@ spserver(void *arg) | | | @@ -802,27 +817,27 @@ spserver(void *arg) |
802 | continue; | | 817 | continue; |
803 | | | 818 | |
804 | seen++; | | 819 | seen++; |
805 | DPRINTF(("rump_sp: activity at [%u] %d/%d\n", | | 820 | DPRINTF(("rump_sp: activity at [%u] %d/%d\n", |
806 | idx, seen, rv)); | | 821 | idx, seen, rv)); |
807 | if (idx > 0) { | | 822 | if (idx > 0) { |
808 | struct spclient *spc = &spclist[idx]; | | 823 | struct spclient *spc = &spclist[idx]; |
809 | | | 824 | |
810 | DPRINTF(("rump_sp: mainloop read [%u]\n", idx)); | | 825 | DPRINTF(("rump_sp: mainloop read [%u]\n", idx)); |
811 | switch (readframe(spc)) { | | 826 | switch (readframe(spc)) { |
812 | case 0: | | 827 | case 0: |
813 | break; | | 828 | break; |
814 | case -1: | | 829 | case -1: |
815 | serv_handle_disco(idx); | | 830 | serv_handledisco(idx); |
816 | break; | | 831 | break; |
817 | default: | | 832 | default: |
818 | spc->spc_off = 0; | | 833 | spc->spc_off = 0; |
819 | serv_handlesyscall(spc, | | 834 | serv_handlesyscall(spc, |
820 | &spc->spc_hdr, spc->spc_buf); | | 835 | &spc->spc_hdr, spc->spc_buf); |
821 | spc->spc_buf = NULL; | | 836 | spc->spc_buf = NULL; |
822 | break; | | 837 | break; |
823 | } | | 838 | } |
824 | } else { | | 839 | } else { |
825 | DPRINTF(("rump_sp: mainloop new connection\n")); | | 840 | DPRINTF(("rump_sp: mainloop new connection\n")); |
826 | serv_handleconn(pfdlist[0].fd, | | 841 | serv_handleconn(pfdlist[0].fd, |
827 | sarg->sps_connhook); | | 842 | sarg->sps_connhook); |
828 | } | | 843 | } |