diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-02-04 21:03:37 -0700 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-02-04 21:03:37 -0700 |
commit | 5c373cfe544df4ddba44adf3f6b60399340e4bd5 (patch) | |
tree | f96f5c57bbb042b3962bed49853621f6d344de04 /lib9p | |
parent | 65f2a6fb8797385e06e61e13bac7a33d27f2097d (diff) | |
parent | 57d4c9f154cacd5d0dcc2f45033d784b3e0b6734 (diff) |
Merge branch 'lukeshu/9p-exit'
Diffstat (limited to 'lib9p')
-rw-r--r-- | lib9p/include/lib9p/srv.h | 2 | ||||
-rw-r--r-- | lib9p/srv.c | 15 | ||||
-rwxr-xr-x | lib9p/tests/runtest | 9 | ||||
-rw-r--r-- | lib9p/tests/test_server/main.c | 105 |
4 files changed, 111 insertions, 20 deletions
diff --git a/lib9p/include/lib9p/srv.h b/lib9p/include/lib9p/srv.h index 55cf5db..d45d9a4 100644 --- a/lib9p/include/lib9p/srv.h +++ b/lib9p/include/lib9p/srv.h @@ -100,6 +100,8 @@ struct lib9p_srv { /* For internal use */ BEGIN_PRIVATE(LIB9P_SRV_H) + unsigned int readers; + unsigned int writers; _lib9p_srv_reqch_t _reqch; END_PRIVATE(LIB9P_SRV_H) }; diff --git a/lib9p/srv.c b/lib9p/srv.c index 7e6402e..10a8a96 100644 --- a/lib9p/srv.c +++ b/lib9p/srv.c @@ -200,6 +200,8 @@ static void handle_message(struct _lib9p_srv_req *ctx); assert(srv->rootdir); assert(listener); + srv->readers++; + uint32_t initial_rerror_overhead = rerror_overhead_for_version(0, buf); for (;;) { @@ -210,7 +212,11 @@ static void handle_message(struct _lib9p_srv_req *ctx); }; if (!conn.fd) { nonrespond_errorf("accept: error"); - continue; + srv->readers--; + if (srv->readers == 0) + while (srv->writers > 0) + _lib9p_srv_reqch_send_req(&srv->_reqch, NULL); + cr_exit(); } struct _srv_sess sess = { @@ -287,9 +293,16 @@ COROUTINE lib9p_srv_write_cr(void *_srv) { assert(srv->rootdir); cr_begin(); + srv->writers++; + for (;;) { /* Receive the request from the reader coroutine. ************/ rpc_handle = _lib9p_srv_reqch_recv_req(&srv->_reqch); + if (!rpc_handle.req) { + srv->writers--; + _lib9p_srv_reqch_send_resp(rpc_handle, 0); + cr_exit(); + } /* Deep-copy the request from the reader coroutine's * stack to our stack. */ req = *rpc_handle.req; diff --git a/lib9p/tests/runtest b/lib9p/tests/runtest index 29d2089..d963c53 100755 --- a/lib9p/tests/runtest +++ b/lib9p/tests/runtest @@ -26,7 +26,8 @@ while [[ -d /proc/$server_pid && "$(readlink /proc/$server_pid/fd/4 2>/dev/null) out=$("${client[@]}" ls -l '') expect_lines \ 'd-r-xr-xr-x M 0 root root 0 Oct 7 15:51 Documentation' \ - '--r--r--r-- M 0 root root 14 Oct 7 15:51 README.md' + '--r--r--r-- M 0 root root 14 Oct 7 15:51 README.md' \ + '---w--w--w- M 0 root root 0 Oct 7 15:51 shutdown' out=$("${client[@]}" ls -l 'Documentation/') expect_lines \ @@ -43,3 +44,9 @@ expect_lines \ out=$("${client[@]}" stat 'Documentation/x') expect_lines \ "'x' 'root' 'root' 'root' q (0000000000000009 1 ) m 0444 at 1728337905 mt 1728337904 l 4 t 0 d 0" + +out=$("${client[@]}" write 'shutdown' <<<1) +expect_lines '' + +wait "$server_pid" +trap - EXIT diff --git a/lib9p/tests/test_server/main.c b/lib9p/tests/test_server/main.c index 8e5011a..71c6cc2 100644 --- a/lib9p/tests/test_server/main.c +++ b/lib9p/tests/test_server/main.c @@ -24,7 +24,80 @@ #error config.h must define CONFIG_SRV9P_NUM_CONNS #endif -/* implementation *************************************************************/ +/* globals ********************************************************************/ + +static implements_lib9p_srv_file *get_root(struct lib9p_srv_ctx *, struct lib9p_s); + +const char *hexdig = "0123456789abcdef"; + +struct { + struct hostnet_tcp_listener listeners[CONFIG_SRV9P_NUM_CONNS]; + struct lib9p_srv srv; +} globals = { + .srv = (struct lib9p_srv){ + .rootdir = get_root, + }, +}; + +/* api ************************************************************************/ + +struct api_file { + implements_lib9p_srv_file; + + uint64_t pathnum; +}; + +static implements_lib9p_srv_file *api_clone(implements_lib9p_srv_file *self, struct lib9p_srv_ctx *) { return self; } +static void api_free(implements_lib9p_srv_file *, struct lib9p_srv_ctx *) {} + +static uint32_t api_io(implements_lib9p_srv_file *, struct lib9p_srv_ctx *, lib9p_o_t) { return 0; } +static void api_wstat(implements_lib9p_srv_file *, struct lib9p_srv_ctx *ctx, struct lib9p_stat) { lib9p_error(&ctx->basectx, LINUX_EROFS, "cannot wstat API file"); } +static void api_remove(implements_lib9p_srv_file *, struct lib9p_srv_ctx *ctx) { lib9p_error(&ctx->basectx, LINUX_EROFS, "cannot remove API file"); } + +static struct lib9p_stat api_stat(implements_lib9p_srv_file *_self, struct lib9p_srv_ctx *) { + struct api_file *self = VCALL_SELF(struct api_file, implements_lib9p_srv_file, _self); + return (struct lib9p_stat){ + .kern_type = 0, + .kern_dev = 0, + .file_qid = { + .type = LIB9P_QT_FILE, + .vers = 1, + .path = self->pathnum, + }, + .file_mode = 0222, + .file_atime = 1728337905, + .file_mtime = 1728337904, + .file_size = 0, + .file_name = lib9p_str("shutdown"), + .file_owner_uid = lib9p_str("root"), + .file_owner_gid = lib9p_str("root"), + .file_last_modified_uid = lib9p_str("root"), + .file_extension = lib9p_str(NULL), + .file_owner_n_uid = 0, + .file_owner_n_gid = 0, + .file_last_modified_n_uid = 0, + }; +} +static uint32_t api_pwrite(implements_lib9p_srv_file *, struct lib9p_srv_ctx *, void *, uint32_t byte_count, uint64_t) { + if (byte_count == 0) + return 0; + for (int i = 0; i < CONFIG_SRV9P_NUM_CONNS; i++) + VCALL(&globals.listeners[i], close); + return byte_count; +} + +static struct lib9p_srv_file_vtable api_file_vtable = { + .clone = api_clone, + .free = api_free, + + .io = api_io, + .stat = api_stat, + .wstat = api_wstat, + .remove = api_remove, + + .pread = NULL, + .pwrite = api_pwrite, +}; /* file tree ******************************************************************/ @@ -74,6 +147,10 @@ static struct util9p_static_dir root = { }, }), STATIC_FILE("README.md", README_md), + &((struct api_file){ + .vtable = &api_file_vtable, + .pathnum = __COUNTER__, + }), NULL, }, }; @@ -84,26 +161,17 @@ static implements_lib9p_srv_file *get_root(struct lib9p_srv_ctx *LM_UNUSED(ctx), /* main ***********************************************************************/ -static COROUTINE read_cr(void *_srv) { - struct lib9p_srv *srv = _srv; - assert(srv); - +static COROUTINE read_cr(void *_i) { + int i = *((int *)_i); cr_begin(); - struct hostnet_tcp_listener listener; - hostnet_tcp_listener_init(&listener, 9000); + hostnet_tcp_listener_init(&globals.listeners[i], 9000); - lib9p_srv_read_cr(srv, &listener); + lib9p_srv_read_cr(&globals.srv, &globals.listeners[i]); cr_end(); } -const char *hexdig = "0123456789abcdef"; - -struct lib9p_srv srv = { - .rootdir = get_root, -}; - static COROUTINE init_cr(void *) { cr_begin(); @@ -111,13 +179,13 @@ static COROUTINE init_cr(void *) { for (int i = 0; i < CONFIG_SRV9P_NUM_CONNS; i++) { char name[] = {'r', 'e', 'a', 'd', '-', hexdig[i], '\0'}; - if (!coroutine_add(name, read_cr, &srv)) - error(1, 0, "coroutine_add(read_cr, &srv)"); + if (!coroutine_add(name, read_cr, &i)) + error(1, 0, "coroutine_add(read_cr, &i)"); } for (int i = 0; i < 2*CONFIG_SRV9P_NUM_CONNS; i++) { char name[] = {'w', 'r', 'i', 't', 'e', '-', hexdig[i], '\0'}; - if (!coroutine_add(name, lib9p_srv_write_cr, &srv)) - error(1, 0, "coroutine_add(lib9p_srv_write_cr, &srv)"); + if (!coroutine_add(name, lib9p_srv_write_cr, &globals.srv)) + error(1, 0, "coroutine_add(lib9p_srv_write_cr, &globals.srv)"); } cr_exit(); @@ -126,4 +194,5 @@ static COROUTINE init_cr(void *) { int main() { coroutine_add("init", init_cr, NULL); coroutine_main(); + return 0; } |