diff options
Diffstat (limited to 'lib9p/tests')
-rw-r--r-- | lib9p/tests/client_config/config.h | 21 | ||||
-rw-r--r-- | lib9p/tests/test_compile.c | 135 | ||||
-rwxr-xr-x | lib9p/tests/test_compile.c.gen | 2 | ||||
-rw-r--r-- | lib9p/tests/test_compile_config/config.h | 19 | ||||
-rw-r--r-- | lib9p/tests/test_server/CMakeLists.txt | 4 | ||||
-rw-r--r-- | lib9p/tests/test_server/config/config.h | 33 | ||||
-rw-r--r-- | lib9p/tests/test_server/fs_flush.c | 136 | ||||
-rw-r--r-- | lib9p/tests/test_server/fs_flush.h | 27 | ||||
-rw-r--r-- | lib9p/tests/test_server/fs_shutdown.c | 41 | ||||
-rw-r--r-- | lib9p/tests/test_server/fs_slowread.c | 101 | ||||
-rw-r--r-- | lib9p/tests/test_server/fs_slowread.h | 22 | ||||
-rw-r--r-- | lib9p/tests/test_server/fs_whoami.c | 158 | ||||
-rw-r--r-- | lib9p/tests/test_server/fs_whoami.h | 20 | ||||
-rw-r--r-- | lib9p/tests/test_server/main.c | 42 | ||||
-rwxr-xr-x | lib9p/tests/testclient-p9p | 10 | ||||
-rw-r--r-- | lib9p/tests/testclient-p9p.explog | 64 | ||||
-rw-r--r-- | lib9p/tests/testclient-sess.c | 119 | ||||
-rw-r--r-- | lib9p/tests/testclient-sess.explog | 136 |
18 files changed, 815 insertions, 275 deletions
diff --git a/lib9p/tests/client_config/config.h b/lib9p/tests/client_config/config.h index 65ee9de..bcf030d 100644 --- a/lib9p/tests/client_config/config.h +++ b/lib9p/tests/client_config/config.h @@ -7,8 +7,6 @@ #ifndef _CONFIG_H_ #define _CONFIG_H_ -/* 9P *************************************************************************/ - #define CONFIG_9P_MAX_ERR_SIZE 128 #define CONFIG_9P_MAX_9P2000_e_WELEM 16 @@ -18,23 +16,4 @@ #define CONFIG_9P_ENABLE_9P2000_L 1 /* bool */ #define CONFIG_9P_ENABLE_9P2000_p9p 1 /* bool */ -/* 9P server (unused) *********************************************************/ - -#define CONFIG_9P_SRV_MAX_MSG_SIZE ((4*1024)+24) -#define CONFIG_9P_SRV_MAX_HOSTMSG_SIZE CONFIG_9P_SRV_MAX_MSG_SIZE+16 -#define CONFIG_9P_SRV_MAX_FIDS 16 -#define CONFIG_9P_SRV_MAX_REQS 2 -#define CONFIG_9P_SRV_MAX_DEPTH 3 - -/* COROUTINE (unused) *********************************************************/ - -#define CONFIG_COROUTINE_STACK_SIZE_DEFAULT (32*1024) -#define CONFIG_COROUTINE_NAME_LEN 16 -#define CONFIG_COROUTINE_MEASURE_STACK 1 /* bool */ -#define CONFIG_COROUTINE_PROTECT_STACK 1 /* bool */ -#define CONFIG_COROUTINE_DEBUG 0 /* bool */ -#define CONFIG_COROUTINE_VALGRIND 1 /* bool */ -#define CONFIG_COROUTINE_GDB 1 /* bool */ -#define CONFIG_COROUTINE_NUM 2 - #endif /* _CONFIG_H_ */ diff --git a/lib9p/tests/test_compile.c b/lib9p/tests/test_compile.c index 8f2445d..4532655 100644 --- a/lib9p/tests/test_compile.c +++ b/lib9p/tests/test_compile.c @@ -1,6 +1,6 @@ /* lib9p/tests/test_compile.c - Generated by lib9p/tests/test_compile.c.gen. DO NOT EDIT! */ -#include <lib9p/9p.h> +#include <lib9p/core.h> int main(void) { [[gnu::unused]] uint64_t x; x = LIB9P_TAG_NOTAG; @@ -47,7 +47,6 @@ int main(void) { x = LIB9P_QT_SYMLINK; x = _LIB9P_QT_UNUSED_0; x = LIB9P_QT_FILE; - x = LIB9P_NUID_NONUID; x = _LIB9P_O_UNUSED_7; x = LIB9P_O_RCLOSE; x = _LIB9P_O_RESERVED_CEXEC; @@ -60,7 +59,139 @@ int main(void) { x = LIB9P_O_MODE_RDWR; x = LIB9P_O_MODE_EXEC; x = LIB9P_O_MODE_MASK; + x = LIB9P_NUID_NONUID; x = LIB9P_ERRNO_NOERROR; + x = LIB9P_ERRNO_L_EPERM; + x = LIB9P_ERRNO_L_ENOENT; + x = LIB9P_ERRNO_L_ESRCH; + x = LIB9P_ERRNO_L_EINTR; + x = LIB9P_ERRNO_L_EIO; + x = LIB9P_ERRNO_L_ENXIO; + x = LIB9P_ERRNO_L_E2BIG; + x = LIB9P_ERRNO_L_ENOEXEC; + x = LIB9P_ERRNO_L_EBADF; + x = LIB9P_ERRNO_L_ECHILD; + x = LIB9P_ERRNO_L_EAGAIN; + x = LIB9P_ERRNO_L_ENOMEM; + x = LIB9P_ERRNO_L_EACCES; + x = LIB9P_ERRNO_L_EFAULT; + x = LIB9P_ERRNO_L_ENOTBLK; + x = LIB9P_ERRNO_L_EBUSY; + x = LIB9P_ERRNO_L_EEXIST; + x = LIB9P_ERRNO_L_EXDEV; + x = LIB9P_ERRNO_L_ENODEV; + x = LIB9P_ERRNO_L_ENOTDIR; + x = LIB9P_ERRNO_L_EISDIR; + x = LIB9P_ERRNO_L_EINVAL; + x = LIB9P_ERRNO_L_ENFILE; + x = LIB9P_ERRNO_L_EMFILE; + x = LIB9P_ERRNO_L_ENOTTY; + x = LIB9P_ERRNO_L_ETXTBSY; + x = LIB9P_ERRNO_L_EFBIG; + x = LIB9P_ERRNO_L_ENOSPC; + x = LIB9P_ERRNO_L_ESPIPE; + x = LIB9P_ERRNO_L_EROFS; + x = LIB9P_ERRNO_L_EMLINK; + x = LIB9P_ERRNO_L_EPIPE; + x = LIB9P_ERRNO_L_EDOM; + x = LIB9P_ERRNO_L_ERANGE; + x = LIB9P_ERRNO_L_EDEADLK; + x = LIB9P_ERRNO_L_ENAMETOOLONG; + x = LIB9P_ERRNO_L_ENOLCK; + x = LIB9P_ERRNO_L_ENOSYS; + x = LIB9P_ERRNO_L_ENOTEMPTY; + x = LIB9P_ERRNO_L_ELOOP; + x = LIB9P_ERRNO_L_ENOMSG; + x = LIB9P_ERRNO_L_EIDRM; + x = LIB9P_ERRNO_L_ECHRNG; + x = LIB9P_ERRNO_L_EL2NSYNC; + x = LIB9P_ERRNO_L_EL3HLT; + x = LIB9P_ERRNO_L_EL3RST; + x = LIB9P_ERRNO_L_ELNRNG; + x = LIB9P_ERRNO_L_EUNATCH; + x = LIB9P_ERRNO_L_ENOCSI; + x = LIB9P_ERRNO_L_EL2HLT; + x = LIB9P_ERRNO_L_EBADE; + x = LIB9P_ERRNO_L_EBADR; + x = LIB9P_ERRNO_L_EXFULL; + x = LIB9P_ERRNO_L_ENOANO; + x = LIB9P_ERRNO_L_EBADRQC; + x = LIB9P_ERRNO_L_EBADSLT; + x = LIB9P_ERRNO_L_EBFONT; + x = LIB9P_ERRNO_L_ENOSTR; + x = LIB9P_ERRNO_L_ENODATA; + x = LIB9P_ERRNO_L_ETIME; + x = LIB9P_ERRNO_L_ENOSR; + x = LIB9P_ERRNO_L_ENONET; + x = LIB9P_ERRNO_L_ENOPKG; + x = LIB9P_ERRNO_L_EREMOTE; + x = LIB9P_ERRNO_L_ENOLINK; + x = LIB9P_ERRNO_L_EADV; + x = LIB9P_ERRNO_L_ESRMNT; + x = LIB9P_ERRNO_L_ECOMM; + x = LIB9P_ERRNO_L_EPROTO; + x = LIB9P_ERRNO_L_EMULTIHOP; + x = LIB9P_ERRNO_L_EDOTDOT; + x = LIB9P_ERRNO_L_EBADMSG; + x = LIB9P_ERRNO_L_EOVERFLOW; + x = LIB9P_ERRNO_L_ENOTUNIQ; + x = LIB9P_ERRNO_L_EBADFD; + x = LIB9P_ERRNO_L_EREMCHG; + x = LIB9P_ERRNO_L_ELIBACC; + x = LIB9P_ERRNO_L_ELIBBAD; + x = LIB9P_ERRNO_L_ELIBSCN; + x = LIB9P_ERRNO_L_ELIBMAX; + x = LIB9P_ERRNO_L_ELIBEXEC; + x = LIB9P_ERRNO_L_EILSEQ; + x = LIB9P_ERRNO_L_ERESTART; + x = LIB9P_ERRNO_L_ESTRPIPE; + x = LIB9P_ERRNO_L_EUSERS; + x = LIB9P_ERRNO_L_ENOTSOCK; + x = LIB9P_ERRNO_L_EDESTADDRREQ; + x = LIB9P_ERRNO_L_EMSGSIZE; + x = LIB9P_ERRNO_L_EPROTOTYPE; + x = LIB9P_ERRNO_L_ENOPROTOOPT; + x = LIB9P_ERRNO_L_EPROTONOSUPPORT; + x = LIB9P_ERRNO_L_ESOCKTNOSUPPORT; + x = LIB9P_ERRNO_L_EOPNOTSUPP; + x = LIB9P_ERRNO_L_EPFNOSUPPORT; + x = LIB9P_ERRNO_L_EAFNOSUPPORT; + x = LIB9P_ERRNO_L_EADDRINUSE; + x = LIB9P_ERRNO_L_EADDRNOTAVAIL; + x = LIB9P_ERRNO_L_ENETDOWN; + x = LIB9P_ERRNO_L_ENETUNREACH; + x = LIB9P_ERRNO_L_ENETRESET; + x = LIB9P_ERRNO_L_ECONNABORTED; + x = LIB9P_ERRNO_L_ECONNRESET; + x = LIB9P_ERRNO_L_ENOBUFS; + x = LIB9P_ERRNO_L_EISCONN; + x = LIB9P_ERRNO_L_ENOTCONN; + x = LIB9P_ERRNO_L_ESHUTDOWN; + x = LIB9P_ERRNO_L_ETOOMANYREFS; + x = LIB9P_ERRNO_L_ETIMEDOUT; + x = LIB9P_ERRNO_L_ECONNREFUSED; + x = LIB9P_ERRNO_L_EHOSTDOWN; + x = LIB9P_ERRNO_L_EHOSTUNREACH; + x = LIB9P_ERRNO_L_EALREADY; + x = LIB9P_ERRNO_L_EINPROGRESS; + x = LIB9P_ERRNO_L_ESTALE; + x = LIB9P_ERRNO_L_EUCLEAN; + x = LIB9P_ERRNO_L_ENOTNAM; + x = LIB9P_ERRNO_L_ENAVAIL; + x = LIB9P_ERRNO_L_EISNAM; + x = LIB9P_ERRNO_L_EREMOTEIO; + x = LIB9P_ERRNO_L_EDQUOT; + x = LIB9P_ERRNO_L_ENOMEDIUM; + x = LIB9P_ERRNO_L_EMEDIUMTYPE; + x = LIB9P_ERRNO_L_ECANCELED; + x = LIB9P_ERRNO_L_ENOKEY; + x = LIB9P_ERRNO_L_EKEYEXPIRED; + x = LIB9P_ERRNO_L_EKEYREVOKED; + x = LIB9P_ERRNO_L_EKEYREJECTED; + x = LIB9P_ERRNO_L_EOWNERDEAD; + x = LIB9P_ERRNO_L_ENOTRECOVERABLE; + x = LIB9P_ERRNO_L_ERFKILL; + x = LIB9P_ERRNO_L_EHWPOISON; x = LIB9P_SUPER_MAGIC_V9FS_MAGIC; x = _LIB9P_LO_UNUSED_31; x = _LIB9P_LO_UNUSED_30; diff --git a/lib9p/tests/test_compile.c.gen b/lib9p/tests/test_compile.c.gen index 47046b3..1289943 100755 --- a/lib9p/tests/test_compile.c.gen +++ b/lib9p/tests/test_compile.c.gen @@ -10,7 +10,7 @@ outfile=$2 { echo "/* ${outfile} - Generated by $0. DO NOT EDIT! */" echo - echo "#include <lib9p/9p.h>" + echo "#include <lib9p/core.h>" echo 'int main(void) {' echo ' [[gnu::unused]] uint64_t x;' sed -nE 's/^\s*#\s*define\s*(\S[^ (]*)\s.*/ x = \1;/p' <"$generated_h" diff --git a/lib9p/tests/test_compile_config/config.h b/lib9p/tests/test_compile_config/config.h index cc8eec1..f899dfa 100644 --- a/lib9p/tests/test_compile_config/config.h +++ b/lib9p/tests/test_compile_config/config.h @@ -7,32 +7,13 @@ #ifndef _CONFIG_H_ #define _CONFIG_H_ -/* 9P *************************************************************************/ - #define CONFIG_9P_MAX_ERR_SIZE 128 #define CONFIG_9P_MAX_9P2000_e_WELEM 16 -#define CONFIG_9P_SRV_MAX_MSG_SIZE ((4*1024)+24) -#define CONFIG_9P_SRV_MAX_HOSTMSG_SIZE CONFIG_9P_SRV_MAX_MSG_SIZE+16 -#define CONFIG_9P_SRV_MAX_FIDS 16 -#define CONFIG_9P_SRV_MAX_REQS 2 -#define CONFIG_9P_SRV_MAX_DEPTH 3 - #define CONFIG_9P_ENABLE_9P2000 1 /* bool */ #define CONFIG_9P_ENABLE_9P2000_u 1 /* bool */ #define CONFIG_9P_ENABLE_9P2000_e 1 /* bool */ #define CONFIG_9P_ENABLE_9P2000_L 1 /* bool */ #define CONFIG_9P_ENABLE_9P2000_p9p 1 /* bool */ -/* COROUTINE ******************************************************************/ - -#define CONFIG_COROUTINE_STACK_SIZE_DEFAULT (32*1024) -#define CONFIG_COROUTINE_NAME_LEN 16 -#define CONFIG_COROUTINE_MEASURE_STACK 1 /* bool */ -#define CONFIG_COROUTINE_PROTECT_STACK 1 /* bool */ -#define CONFIG_COROUTINE_DEBUG 0 /* bool */ -#define CONFIG_COROUTINE_VALGRIND 1 /* bool */ -#define CONFIG_COROUTINE_GDB 1 /* bool */ -#define CONFIG_COROUTINE_NUM 2 - #endif /* _CONFIG_H_ */ diff --git a/lib9p/tests/test_server/CMakeLists.txt b/lib9p/tests/test_server/CMakeLists.txt index eb16165..c61d344 100644 --- a/lib9p/tests/test_server/CMakeLists.txt +++ b/lib9p/tests/test_server/CMakeLists.txt @@ -9,8 +9,9 @@ if (PICO_PLATFORM STREQUAL "host") add_library(test_server_objs OBJECT main.c + fs_flush.c fs_shutdown.c - fs_slowread.c + fs_whoami.c ) target_include_directories(test_server_objs PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/config) target_include_directories(test_server_objs PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) @@ -18,7 +19,6 @@ target_link_libraries(test_server_objs libcr libcr_ipc libmisc - lib9p lib9p_util libhw_cr ) diff --git a/lib9p/tests/test_server/config/config.h b/lib9p/tests/test_server/config/config.h index 03143e1..f49894b 100644 --- a/lib9p/tests/test_server/config/config.h +++ b/lib9p/tests/test_server/config/config.h @@ -7,13 +7,23 @@ #ifndef _CONFIG_H_ #define _CONFIG_H_ -#define _CONFIG_9P_NUM_SOCKS 8 -#define CONFIG_SRV9P_NUM_CONNS _CONFIG_9P_NUM_SOCKS +#define _CONFIG_9P_MAX_CONNS 8 +#define _CONFIG_9P_MAX_REQS (2*_CONFIG_9P_MAX_CONNS) /* 9P *************************************************************************/ #define CONFIG_9P_MAX_ERR_SIZE 128 /* 128 is what Plan 9 4e uses */ +#define CONFIG_9P_ENABLE_9P2000 1 /* bool */ +#define CONFIG_9P_ENABLE_9P2000_u 1 /* bool */ +#define CONFIG_9P_ENABLE_9P2000_e 0 /* bool */ +#define CONFIG_9P_ENABLE_9P2000_L 0 /* bool */ +#define CONFIG_9P_ENABLE_9P2000_p9p 0 /* bool */ + +/* 9P_SRV *********************************************************************/ + +#define CONFIG_9P_SRV_DEBUG 1 /* bool */ + /** * This max-msg-size is sized so that a Twrite message can return * 8KiB of data. @@ -38,15 +48,6 @@ * struct padding, (2) array pointers. */ #define CONFIG_9P_SRV_MAX_HOSTMSG_SIZE CONFIG_9P_SRV_MAX_MSG_SIZE+16 -#define CONFIG_9P_SRV_MAX_FIDS 16 -#define CONFIG_9P_SRV_MAX_REQS 2 -#define CONFIG_9P_SRV_MAX_DEPTH 3 - -#define CONFIG_9P_ENABLE_9P2000 1 /* bool */ -#define CONFIG_9P_ENABLE_9P2000_u 1 /* bool */ -#define CONFIG_9P_ENABLE_9P2000_e 0 /* bool */ -#define CONFIG_9P_ENABLE_9P2000_L 0 /* bool */ -#define CONFIG_9P_ENABLE_9P2000_p9p 0 /* bool */ /* COROUTINE ******************************************************************/ @@ -57,10 +58,10 @@ #define CONFIG_COROUTINE_DEBUG 0 /* bool */ #define CONFIG_COROUTINE_VALGRIND 1 /* bool */ #define CONFIG_COROUTINE_GDB 1 /* bool */ -#define CONFIG_COROUTINE_NUM ( \ - 1 /* usb_common */ + \ - 1 /* usb_keyboard */ + \ - CONFIG_SRV9P_NUM_CONNS /* accept+read */ + \ - (CONFIG_9P_SRV_MAX_REQS*CONFIG_SRV9P_NUM_CONNS) /* work+write */ ) +#define CONFIG_COROUTINE_NUM ( \ + 1 /* usb_common */ + \ + 1 /* usb_keyboard */ + \ + _CONFIG_9P_MAX_CONNS /* accept+read */ + \ + _CONFIG_9P_MAX_REQS /* work+write */ ) #endif /* _CONFIG_H_ */ diff --git a/lib9p/tests/test_server/fs_flush.c b/lib9p/tests/test_server/fs_flush.c new file mode 100644 index 0000000..779eb91 --- /dev/null +++ b/lib9p/tests/test_server/fs_flush.c @@ -0,0 +1,136 @@ +/* lib9p/tests/test_server/fs_flush.c - flush-* API endpoints + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <libmisc/alloc.h> + +#define IMPLEMENTATION_FOR_LIB9P_SRV_H YES /* for ctx->flush_ch */ +#include "fs_flush.h" + +LO_IMPLEMENTATION_C(lib9p_srv_file, struct flush_file, flush_file, static); + +struct flush_fio { + struct flush_file *parent; +}; +LO_IMPLEMENTATION_H(lib9p_srv_fio, struct flush_fio, flush_fio); +LO_IMPLEMENTATION_C(lib9p_srv_fio, struct flush_fio, flush_fio, static); + +/* srv_file *******************************************************************/ + +static void flush_file_free(struct flush_file *self) { + assert(self); +} +static struct lib9p_qid flush_file_qid(struct flush_file *self) { + assert(self); + return (struct lib9p_qid){ + .type = LIB9P_QT_FILE, + .vers = 1, + .path = self->pathnum, + }; +} + +static struct lib9p_stat flush_file_stat(struct flush_file *self, struct lib9p_srv_ctx *ctx) { + assert(self); + assert(ctx); + return (struct lib9p_stat){ + .kern_type = 0, + .kern_dev = 0, + .file_qid = flush_file_qid(self), + .file_mode = 0444, + .file_atime = UTIL9P_ATIME, + .file_mtime = UTIL9P_MTIME, + .file_size = 6, + .file_name = lib9p_str(self->name), + .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 void flush_file_wstat(struct flush_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_stat) { + assert(self); + assert(ctx); + lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "cannot wstat API file"); +} +static void flush_file_remove(struct flush_file *self, struct lib9p_srv_ctx *ctx) { + assert(self); + assert(ctx); + lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "cannot remove API file"); +} + +LIB9P_SRV_NOTDIR(struct flush_file, flush_file) + +static lo_interface lib9p_srv_fio flush_file_fopen(struct flush_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { + assert(self); + assert(ctx); + + struct flush_fio *ret = heap_alloc(1, struct flush_fio); + ret->parent = self; + + return lo_box_flush_fio_as_lib9p_srv_fio(ret); +} + +/* srv_fio ********************************************************************/ + +static void flush_fio_iofree(struct flush_fio *self) { + assert(self); + free(self); +} + +static struct lib9p_qid flush_fio_qid(struct flush_fio *self) { + assert(self); + return flush_file_qid(self->parent); +} + +static uint32_t flush_fio_iounit(struct flush_fio *self) { + assert(self); + return 0; +} + +static uint32_t flush_fio_pwrite(struct flush_fio *LM_UNUSED(self), + struct lib9p_srv_ctx *LM_UNUSED(ctx), + void *LM_UNUSED(buf), uint32_t LM_UNUSED(byte_count), + uint64_t LM_UNUSED(offset)) { + assert_notreached("not writable"); +} + +static void flush_fio_pread(struct flush_fio *self, struct lib9p_srv_ctx *ctx, + uint32_t byte_count, uint64_t LM_UNUSED(byte_offset), + struct iovec *ret) { + assert(self); + assert(ctx); + assert(ret); + + /* Wait for first Tflush */ + while (!lib9p_srv_flush_requested(ctx)) + cr_yield(); + + /* Wait for the specified number of Tflush (may be higher *or* + * lower than 1; lower would mean that the first Tflush needs + * to be flushed itself). */ + while (cr_chan_num_waiters(&ctx->flush_ch) != self->parent->flush_cnt) + cr_yield(); + + /* Return */ + switch (self->parent->flush_behavior) { + case FLUSH_READ: + *ret = (struct iovec){ + .iov_base = "Sloth\n", + .iov_len = 6 < byte_count ? 6 : byte_count, + }; + break; + case FLUSH_ERROR: + lib9p_srv_acknowledge_flush(ctx); + lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_ECANCELED, "request canceled by flush"); + break; + case FLUSH_SILENT: + lib9p_srv_acknowledge_flush(ctx); + break; + } + cr_yield(); +} diff --git a/lib9p/tests/test_server/fs_flush.h b/lib9p/tests/test_server/fs_flush.h new file mode 100644 index 0000000..a509c4a --- /dev/null +++ b/lib9p/tests/test_server/fs_flush.h @@ -0,0 +1,27 @@ +/* lib9p/tests/test_server/fs_flush.h - flush-* API endpoints + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#ifndef _LIB9P_TESTS_TEST_SERVER_FS_FLUSH_H_ +#define _LIB9P_TESTS_TEST_SERVER_FS_FLUSH_H_ + +#include <util9p/static.h> +#include <libhw/host_net.h> + +struct flush_file { + char *name; + uint64_t pathnum; + + unsigned int flush_cnt; + enum { + FLUSH_READ, + FLUSH_ERROR, + FLUSH_SILENT, + } flush_behavior; +}; +LO_IMPLEMENTATION_H(lib9p_srv_file, struct flush_file, flush_file); +#define lo_box_flush_file_as_lib9p_srv_file(obj) util9p_box(flush_file, obj) + +#endif /* _LIB9P_TESTS_TEST_SERVER_FS_FLUSH_H_ */ diff --git a/lib9p/tests/test_server/fs_shutdown.c b/lib9p/tests/test_server/fs_shutdown.c index 3f88985..e7375ef 100644 --- a/lib9p/tests/test_server/fs_shutdown.c +++ b/lib9p/tests/test_server/fs_shutdown.c @@ -4,12 +4,17 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ +#include <libmisc/alloc.h> + #include "fs_shutdown.h" LO_IMPLEMENTATION_C(lib9p_srv_file, struct shutdown_file, shutdown_file, static); -LO_IMPLEMENTATION_H(lib9p_srv_fio, struct shutdown_file, shutdown_file); -LO_IMPLEMENTATION_C(lib9p_srv_fio, struct shutdown_file, shutdown_file, static); +struct shutdown_fio { + struct shutdown_file *parent; +}; +LO_IMPLEMENTATION_H(lib9p_srv_fio, struct shutdown_fio, shutdown_fio); +LO_IMPLEMENTATION_C(lib9p_srv_fio, struct shutdown_fio, shutdown_fio, static); /* srv_file *******************************************************************/ @@ -49,12 +54,12 @@ static struct lib9p_stat shutdown_file_stat(struct shutdown_file *self, struct l static void shutdown_file_wstat(struct shutdown_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_stat) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LINUX_EROFS, "cannot wstat API file"); + lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "cannot wstat API file"); } static void shutdown_file_remove(struct shutdown_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LINUX_EROFS, "cannot remove API file"); + lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "cannot remove API file"); } LIB9P_SRV_NOTDIR(struct shutdown_file, shutdown_file) @@ -62,32 +67,42 @@ LIB9P_SRV_NOTDIR(struct shutdown_file, shutdown_file) static lo_interface lib9p_srv_fio shutdown_file_fopen(struct shutdown_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { assert(self); assert(ctx); - return lo_box_shutdown_file_as_lib9p_srv_fio(self); + + struct shutdown_fio *ret = heap_alloc(1, struct shutdown_fio); + ret->parent = self; + + return lo_box_shutdown_fio_as_lib9p_srv_fio(ret); } /* srv_fio ********************************************************************/ -static void shutdown_file_iofree(struct shutdown_file *self) { +static void shutdown_fio_iofree(struct shutdown_fio *self) { + assert(self); + free(self); +} + +static struct lib9p_qid shutdown_fio_qid(struct shutdown_fio *self) { assert(self); + return shutdown_file_qid(self->parent); } -static uint32_t shutdown_file_iounit(struct shutdown_file *self) { +static uint32_t shutdown_fio_iounit(struct shutdown_fio *self) { assert(self); return 0; } -static uint32_t shutdown_file_pwrite(struct shutdown_file *self, struct lib9p_srv_ctx *ctx, void *buf, uint32_t byte_count, uint64_t LM_UNUSED(offset)) { +static uint32_t shutdown_fio_pwrite(struct shutdown_fio *self, struct lib9p_srv_ctx *ctx, void *buf, uint32_t byte_count, uint64_t LM_UNUSED(offset)) { assert(self); assert(ctx); assert(buf); if (byte_count == 0) return 0; - for (size_t i = 0; i < self->nlisteners; i++) - LO_CALL(lo_box_hostnet_tcplist_as_net_stream_listener(&self->listeners[i]), close); + for (size_t i = 0; i < self->parent->nlisteners; i++) + LO_CALL(lo_box_hostnet_tcplist_as_net_stream_listener(&self->parent->listeners[i]), close); return byte_count; } -static void shutdown_file_pread(struct shutdown_file *LM_UNUSED(self), struct lib9p_srv_ctx *LM_UNUSED(ctx), - uint32_t LM_UNUSED(byte_count), uint64_t LM_UNUSED(byte_offset), - struct iovec *LM_UNUSED(ret)) { +static void shutdown_fio_pread(struct shutdown_fio *LM_UNUSED(self), struct lib9p_srv_ctx *LM_UNUSED(ctx), + uint32_t LM_UNUSED(byte_count), uint64_t LM_UNUSED(byte_offset), + struct iovec *LM_UNUSED(ret)) { assert_notreached("not readable"); } diff --git a/lib9p/tests/test_server/fs_slowread.c b/lib9p/tests/test_server/fs_slowread.c deleted file mode 100644 index 520edd2..0000000 --- a/lib9p/tests/test_server/fs_slowread.c +++ /dev/null @@ -1,101 +0,0 @@ -/* lib9p/tests/test_server/fs_slowread.c - slowread API endpoint - * - * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -#include "fs_slowread.h" - -LO_IMPLEMENTATION_C(lib9p_srv_file, struct slowread_file, slowread_file, static); - -LO_IMPLEMENTATION_H(lib9p_srv_fio, struct slowread_file, slowread_file); -LO_IMPLEMENTATION_C(lib9p_srv_fio, struct slowread_file, slowread_file, static); - -/* srv_file *******************************************************************/ - -static void slowread_file_free(struct slowread_file *self) { - assert(self); -} -static struct lib9p_qid slowread_file_qid(struct slowread_file *self) { - assert(self); - return (struct lib9p_qid){ - .type = LIB9P_QT_FILE, - .vers = 1, - .path = self->pathnum, - }; -} - -static struct lib9p_stat slowread_file_stat(struct slowread_file *self, struct lib9p_srv_ctx *ctx) { - assert(self); - assert(ctx); - return (struct lib9p_stat){ - .kern_type = 0, - .kern_dev = 0, - .file_qid = slowread_file_qid(self), - .file_mode = 0444, - .file_atime = UTIL9P_ATIME, - .file_mtime = UTIL9P_MTIME, - .file_size = 6, - .file_name = lib9p_str(self->name), - .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 void slowread_file_wstat(struct slowread_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_stat) { - assert(self); - assert(ctx); - lib9p_error(&ctx->basectx, LINUX_EROFS, "cannot wstat API file"); -} -static void slowread_file_remove(struct slowread_file *self, struct lib9p_srv_ctx *ctx) { - assert(self); - assert(ctx); - lib9p_error(&ctx->basectx, LINUX_EROFS, "cannot remove API file"); -} - -LIB9P_SRV_NOTDIR(struct slowread_file, slowread_file) - -static lo_interface lib9p_srv_fio slowread_file_fopen(struct slowread_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { - assert(self); - assert(ctx); - return lo_box_slowread_file_as_lib9p_srv_fio(self); -} - -/* srv_fio ********************************************************************/ - -static void slowread_file_iofree(struct slowread_file *self) { - assert(self); -} - -static uint32_t slowread_file_iounit(struct slowread_file *self) { - assert(self); - return 0; -} - -static uint32_t slowread_file_pwrite(struct slowread_file *LM_UNUSED(self), - struct lib9p_srv_ctx *LM_UNUSED(ctx), - void *LM_UNUSED(buf), uint32_t LM_UNUSED(byte_count), - uint64_t LM_UNUSED(offset)) { - assert_notreached("not writable"); -} -static void slowread_file_pread(struct slowread_file *self, struct lib9p_srv_ctx *ctx, - uint32_t byte_count, uint64_t LM_UNUSED(byte_offset), - struct iovec *ret) { - assert(self); - assert(ctx); - assert(ret); - - while (!lib9p_srv_flush_requested(ctx)) - cr_yield(); - if (self->flushable) - lib9p_srv_acknowledge_flush(ctx); - else - *ret = (struct iovec){ - .iov_base = "Sloth\n", - .iov_len = 6 < byte_count ? 6 : byte_count, - }; -} diff --git a/lib9p/tests/test_server/fs_slowread.h b/lib9p/tests/test_server/fs_slowread.h deleted file mode 100644 index ef4b65f..0000000 --- a/lib9p/tests/test_server/fs_slowread.h +++ /dev/null @@ -1,22 +0,0 @@ -/* lib9p/tests/test_server/fs_slowread.h - slowread API endpoint - * - * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -#ifndef _LIB9P_TESTS_TEST_SERVER_FS_SLOWREAD_H_ -#define _LIB9P_TESTS_TEST_SERVER_FS_SLOWREAD_H_ - -#include <util9p/static.h> -#include <libhw/host_net.h> - -struct slowread_file { - char *name; - uint64_t pathnum; - - bool flushable; -}; -LO_IMPLEMENTATION_H(lib9p_srv_file, struct slowread_file, slowread_file); -#define lo_box_slowread_file_as_lib9p_srv_file(obj) util9p_box(slowread_file, obj) - -#endif /* _LIB9P_TESTS_TEST_SERVER_FS_SLOWREAD_H_ */ diff --git a/lib9p/tests/test_server/fs_whoami.c b/lib9p/tests/test_server/fs_whoami.c new file mode 100644 index 0000000..653ac4b --- /dev/null +++ b/lib9p/tests/test_server/fs_whoami.c @@ -0,0 +1,158 @@ +/* lib9p/tests/test_server/fs_whoami.c - /whoami API endpoint + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <stdio.h> /* for snprintf() */ +#include <stdlib.h> /* for realloc(), free() */ + +#include <libmisc/alloc.h> + +#include "fs_whoami.h" + +LO_IMPLEMENTATION_C(lib9p_srv_file, struct whoami_file, whoami_file, static); + +struct whoami_fio { + struct whoami_file *parent; + size_t buf_len; + char *buf; +}; +LO_IMPLEMENTATION_H(lib9p_srv_fio, struct whoami_fio, whoami_fio); +LO_IMPLEMENTATION_C(lib9p_srv_fio, struct whoami_fio, whoami_fio, static); + +size_t whoami_len(struct lib9p_srv_ctx *ctx) { + assert(ctx); + assert(ctx->authinfo); + + size_t len = 0; + uint32_t uid = ctx->authinfo->uid; + while (uid) { + len++; + uid /= 10; + } + if (!len) + len++; + len += 2; + len += ctx->authinfo->uname.len; + return len; +} + +/* srv_file *******************************************************************/ + +static void whoami_file_free(struct whoami_file *self) { + assert(self); +} +static struct lib9p_qid whoami_file_qid(struct whoami_file *self) { + assert(self); + return (struct lib9p_qid){ + .type = LIB9P_QT_FILE, + .vers = 1, + .path = self->pathnum, + }; +} + +static struct lib9p_stat whoami_file_stat(struct whoami_file *self, struct lib9p_srv_ctx *ctx) { + assert(self); + assert(ctx); + + return (struct lib9p_stat){ + .kern_type = 0, + .kern_dev = 0, + .file_qid = whoami_file_qid(self), + .file_mode = 0444, + .file_atime = UTIL9P_ATIME, + .file_mtime = UTIL9P_MTIME, + .file_size = whoami_len(ctx), + .file_name = lib9p_str(self->name), + .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 void whoami_file_wstat(struct whoami_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_stat) { + assert(self); + assert(ctx); + lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "cannot wstat API file"); +} +static void whoami_file_remove(struct whoami_file *self, struct lib9p_srv_ctx *ctx) { + assert(self); + assert(ctx); + lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "cannot remove API file"); +} + +LIB9P_SRV_NOTDIR(struct whoami_file, whoami_file) + +static lo_interface lib9p_srv_fio whoami_file_fopen(struct whoami_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { + assert(self); + assert(ctx); + + struct whoami_fio *ret = heap_alloc(1, struct whoami_fio); + ret->parent = self; + ret->buf_len = 0; + ret->buf = NULL; + + return lo_box_whoami_fio_as_lib9p_srv_fio(ret); +} + +/* srv_fio ********************************************************************/ + +static void whoami_fio_iofree(struct whoami_fio *self) { + assert(self); + if (self->buf) + free(self->buf); + free(self); +} + +static struct lib9p_qid whoami_fio_qid(struct whoami_fio *self) { + assert(self); + assert(self->parent); + return whoami_file_qid(self->parent); +} + +static uint32_t whoami_fio_iounit(struct whoami_fio *self) { + assert(self); + return 0; +} + +static uint32_t whoami_fio_pwrite(struct whoami_fio *LM_UNUSED(self), + struct lib9p_srv_ctx *LM_UNUSED(ctx), + void *LM_UNUSED(buf), uint32_t LM_UNUSED(byte_count), + uint64_t LM_UNUSED(offset)) { + assert_notreached("not writable"); +} +static void whoami_fio_pread(struct whoami_fio *self, struct lib9p_srv_ctx *ctx, + uint32_t byte_count, uint64_t byte_offset, + struct iovec *ret) { + assert(self); + assert(ctx); + assert(ret); + + size_t data_size = whoami_len(ctx); + if (self->buf_len < data_size+1) { + self->buf = realloc(self->buf, data_size+1); + self->buf_len = data_size+1; + } + snprintf(self->buf, self->buf_len, "%"PRIu32" %.*s\n", + ctx->authinfo->uid, ctx->authinfo->uname.len, ctx->authinfo->uname.utf8); + + if (byte_offset > (uint64_t)data_size) { + lib9p_error(&ctx->basectx, + LIB9P_ERRNO_L_EINVAL, "offset is past end-of-file length"); + return; + } + + size_t beg_off = (size_t)byte_offset; + size_t end_off = beg_off + (size_t)byte_count; + if (end_off > data_size) + end_off = data_size; + + *ret = (struct iovec){ + .iov_base = &self->buf[beg_off], + .iov_len = end_off-beg_off, + }; +} diff --git a/lib9p/tests/test_server/fs_whoami.h b/lib9p/tests/test_server/fs_whoami.h new file mode 100644 index 0000000..0d3d311 --- /dev/null +++ b/lib9p/tests/test_server/fs_whoami.h @@ -0,0 +1,20 @@ +/* lib9p/tests/test_server/fs_whoami.h - /whoami API endpoint + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#ifndef _LIB9P_TESTS_TEST_SERVER_FS_WHOAMI_H_ +#define _LIB9P_TESTS_TEST_SERVER_FS_WHOAMI_H_ + +#include <util9p/static.h> +#include <libhw/host_net.h> + +struct whoami_file { + char *name; + uint64_t pathnum; +}; +LO_IMPLEMENTATION_H(lib9p_srv_file, struct whoami_file, whoami_file); +#define lo_box_whoami_file_as_lib9p_srv_file(obj) util9p_box(whoami_file, obj) + +#endif /* _LIB9P_TESTS_TEST_SERVER_FS_WHOAMI_H_ */ diff --git a/lib9p/tests/test_server/main.c b/lib9p/tests/test_server/main.c index 2743629..d7819eb 100644 --- a/lib9p/tests/test_server/main.c +++ b/lib9p/tests/test_server/main.c @@ -19,15 +19,19 @@ #include <util9p/static.h> #include "static.h" +#include "fs_flush.h" #include "fs_shutdown.h" -#include "fs_slowread.h" +#include "fs_whoami.h" /* configuration **************************************************************/ #include "config.h" -#ifndef CONFIG_SRV9P_NUM_CONNS - #error config.h must define CONFIG_SRV9P_NUM_CONNS +#ifndef _CONFIG_9P_MAX_CONNS + #error config.h must define _CONFIG_9P_MAX_CONNS +#endif +#ifndef _CONFIG_9P_MAX_REQS + #error config.h must define _CONFIG_9P_MAX_REQS #endif /* globals ********************************************************************/ @@ -38,7 +42,7 @@ const char *hexdig = "0123456789abcdef"; struct { uint16_t port; - struct hostnet_tcp_listener listeners[CONFIG_SRV9P_NUM_CONNS]; + struct hostnet_tcp_listener listeners[_CONFIG_9P_MAX_CONNS]; struct lib9p_srv srv; FILE *logstream; } globals = { @@ -72,10 +76,12 @@ struct lib9p_srv_file root = API_FILE(5, "shutdown", shutdown, .listeners = globals.listeners, .nlisteners = LM_ARRAY_LEN(globals.listeners)), - API_FILE(6, "slowread", slowread, - .flushable = false), - API_FILE(7, "slowread-flushable", slowread, - .flushable = true), + API_FILE(8, "whoami", whoami), + API_FILE(9, "flush-read", flush, .flush_cnt=1, .flush_behavior=FLUSH_READ), + API_FILE(10, "flush-error", flush, .flush_cnt=1, .flush_behavior=FLUSH_ERROR), + API_FILE(11, "flush-silent", flush, .flush_cnt=1, .flush_behavior=FLUSH_SILENT), + API_FILE(12, "flush-slowsilent", flush, .flush_cnt=2, .flush_behavior=FLUSH_SILENT), + API_FILE(13, "flush-slowread", flush, .flush_cnt=0, .flush_behavior=FLUSH_READ), ); static lo_interface lib9p_srv_file get_root(struct lib9p_srv_ctx *LM_UNUSED(ctx), struct lib9p_s LM_UNUSED(treename)) { @@ -90,7 +96,15 @@ static COROUTINE read_cr(void *_i) { hostnet_tcp_listener_init(&globals.listeners[i], globals.port); - lib9p_srv_read_cr(&globals.srv, lo_box_hostnet_tcplist_as_net_stream_listener(&globals.listeners[i])); + lib9p_srv_accept_and_read_loop(&globals.srv, lo_box_hostnet_tcplist_as_net_stream_listener(&globals.listeners[i])); + + cr_end(); +} + +static COROUTINE write_cr(void *) { + cr_begin(); + + lib9p_srv_worker_loop(&globals.srv); cr_end(); } @@ -98,17 +112,17 @@ static COROUTINE read_cr(void *_i) { static COROUTINE init_cr(void *) { cr_begin(); - sleep_for_ms(1); + sleep_for_ms(1); /* test that sleep works */ - for (int i = 0; i < CONFIG_SRV9P_NUM_CONNS; i++) { + for (int i = 0; i < _CONFIG_9P_MAX_CONNS; i++) { char name[] = {'r', 'e', 'a', 'd', '-', hexdig[i], '\0'}; 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++) { + for (int i = 0; i < _CONFIG_9P_MAX_REQS; i++) { char name[] = {'w', 'r', 'i', 't', 'e', '-', hexdig[i], '\0'}; - if (!coroutine_add(name, lib9p_srv_write_cr, &globals.srv)) - error(1, 0, "coroutine_add(lib9p_srv_write_cr, &globals.srv)"); + if (!coroutine_add(name, write_cr, NULL)) + error(1, 0, "coroutine_add(write_cr, NULL)"); } cr_exit(); diff --git a/lib9p/tests/testclient-p9p b/lib9p/tests/testclient-p9p index 81a7e50..9c9f9f2 100755 --- a/lib9p/tests/testclient-p9p +++ b/lib9p/tests/testclient-p9p @@ -19,15 +19,19 @@ expect_lines() ( ) set -x -client=(9p -a "localhost:${1}") +client=(unshare --user 9p -a "localhost:${1}") out=$("${client[@]}" ls -l '') expect_lines \ 'd-r-xr-xr-x M 0 root root 0 Oct 7 2024 Documentation' \ '--r--r--r-- M 0 root root 166 Oct 7 2024 README.md' \ + '--r--r--r-- M 0 root root 6 Oct 7 2024 flush-error' \ + '--r--r--r-- M 0 root root 6 Oct 7 2024 flush-read' \ + '--r--r--r-- M 0 root root 6 Oct 7 2024 flush-silent' \ + '--r--r--r-- M 0 root root 6 Oct 7 2024 flush-slowread' \ + '--r--r--r-- M 0 root root 6 Oct 7 2024 flush-slowsilent' \ '---w--w--w- M 0 root root 0 Oct 7 2024 shutdown' \ - '--r--r--r-- M 0 root root 6 Oct 7 2024 slowread' \ - '--r--r--r-- M 0 root root 6 Oct 7 2024 slowread-flushable' + '--r--r--r-- M 0 root root 9 Oct 7 2024 whoami' out=$("${client[@]}" ls -l 'Documentation/') expect_lines \ diff --git a/lib9p/tests/testclient-p9p.explog b/lib9p/tests/testclient-p9p.explog index 3bfb0b0..7f3953d 100644 --- a/lib9p/tests/testclient-p9p.explog +++ b/lib9p/tests/testclient-p9p.explog @@ -4,9 +4,9 @@ # SPDX-License-Identifier: AGPL-3.0-or-later > Tversion { tag=NOTAG max_msg_size=8192 version="9P2000" } < Rversion { tag=NOTAG max_msg_size=4120 version="9P2000" } -> Tauth { tag=0 afid=0 uname="lukeshu" aname="" n_uid=0 } -< Rerror { tag=0 errstr="authentication not required" errnum=95 } -> Tattach { tag=0 fid=0 afid=NOFID uname="lukeshu" aname="" n_uid=0 } +> Tauth { tag=0 afid=0 uname="nobody" aname="" n_uid=0 } +< Rerror { tag=0 errstr="authentication not required" errnum=L_EOPNOTSUPP } +> Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" n_uid=0 } < Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } > Twalk { tag=0 fid=0 newfid=1 nwname=0 wname=[ ] } < Rwalk { tag=0 nwqid=0 wqid=[ ] } @@ -19,25 +19,25 @@ > Topen { tag=0 fid=1 mode=(MODE_READ) } < Ropen { tag=0 qid={ type=(DIR) vers=1 path=1 } iounit=0 } > Tread { tag=0 fid=1 offset=0 count=4096 } -< Rread { tag=0 count=361 data=<bytedata> } -> Tread { tag=0 fid=1 offset=361 count=4096 } +< Rread { tag=0 count=648 data=<bytedata> } +> Tread { tag=0 fid=1 offset=648 count=4096 } < Rread { tag=0 count=0 data="" } > Tclunk { tag=0 fid=1 } < Rclunk { tag=0 } > Tversion { tag=NOTAG max_msg_size=8192 version="9P2000" } < Rversion { tag=NOTAG max_msg_size=4120 version="9P2000" } -> Tauth { tag=0 afid=0 uname="lukeshu" aname="" n_uid=0 } -< Rerror { tag=0 errstr="authentication not required" errnum=95 } -> Tattach { tag=0 fid=0 afid=NOFID uname="lukeshu" aname="" n_uid=0 } +> Tauth { tag=0 afid=0 uname="nobody" aname="" n_uid=0 } +< Rerror { tag=0 errstr="authentication not required" errnum=L_EOPNOTSUPP } +> Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" n_uid=0 } < Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } -> Twalk { tag=0 fid=0 newfid=1 nwname=1 wname=["Documentation" ] } -< Rwalk { tag=0 nwqid=1 wqid=[{ type=(DIR) vers=1 path=2 } ] } +> Twalk { tag=0 fid=0 newfid=1 nwname=1 wname=[ "Documentation" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(DIR) vers=1 path=2 } ] } > Tstat { tag=0 fid=1 } < Rstat { tag=0 stat={ kern_type=0 kern_dev=0 file_qid={ type=(DIR) vers=1 path=2 } file_mode=(DIR|0555) file_atime=1728337905 file_mtime=1728337904 file_size=0 file_name="Documentation" file_owner_uid="root" file_owner_gid="root" file_last_modified_uid="root" file_extension="" file_owner_n_uid=0 file_owner_n_gid=0 file_last_modified_n_uid=0 } } > Tclunk { tag=0 fid=1 } < Rclunk { tag=0 } -> Twalk { tag=0 fid=0 newfid=1 nwname=1 wname=["Documentation" ] } -< Rwalk { tag=0 nwqid=1 wqid=[{ type=(DIR) vers=1 path=2 } ] } +> Twalk { tag=0 fid=0 newfid=1 nwname=1 wname=[ "Documentation" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(DIR) vers=1 path=2 } ] } > Topen { tag=0 fid=1 mode=(MODE_READ) } < Ropen { tag=0 qid={ type=(DIR) vers=1 path=2 } iounit=0 } > Tread { tag=0 fid=1 offset=0 count=4096 } @@ -48,12 +48,12 @@ < Rclunk { tag=0 } > Tversion { tag=NOTAG max_msg_size=8192 version="9P2000" } < Rversion { tag=NOTAG max_msg_size=4120 version="9P2000" } -> Tauth { tag=0 afid=0 uname="lukeshu" aname="" n_uid=0 } -< Rerror { tag=0 errstr="authentication not required" errnum=95 } -> Tattach { tag=0 fid=0 afid=NOFID uname="lukeshu" aname="" n_uid=0 } +> Tauth { tag=0 afid=0 uname="nobody" aname="" n_uid=0 } +< Rerror { tag=0 errstr="authentication not required" errnum=L_EOPNOTSUPP } +> Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" n_uid=0 } < Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } -> Twalk { tag=0 fid=0 newfid=1 nwname=1 wname=["README.md" ] } -< Rwalk { tag=0 nwqid=1 wqid=[{ type=(0) vers=1 path=4 } ] } +> Twalk { tag=0 fid=0 newfid=1 nwname=1 wname=[ "README.md" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=4 } ] } > Topen { tag=0 fid=1 mode=(MODE_READ) } < Ropen { tag=0 qid={ type=(0) vers=1 path=4 } iounit=0 } > Tread { tag=0 fid=1 offset=0 count=4096 } @@ -64,12 +64,12 @@ < Rclunk { tag=0 } > Tversion { tag=NOTAG max_msg_size=8192 version="9P2000" } < Rversion { tag=NOTAG max_msg_size=4120 version="9P2000" } -> Tauth { tag=0 afid=0 uname="lukeshu" aname="" n_uid=0 } -< Rerror { tag=0 errstr="authentication not required" errnum=95 } -> Tattach { tag=0 fid=0 afid=NOFID uname="lukeshu" aname="" n_uid=0 } +> Tauth { tag=0 afid=0 uname="nobody" aname="" n_uid=0 } +< Rerror { tag=0 errstr="authentication not required" errnum=L_EOPNOTSUPP } +> Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" n_uid=0 } < Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } -> Twalk { tag=0 fid=0 newfid=1 nwname=2 wname=["Documentation", "x" ] } -< Rwalk { tag=0 nwqid=2 wqid=[{ type=(DIR) vers=1 path=2 }, { type=(0) vers=1 path=3 } ] } +> Twalk { tag=0 fid=0 newfid=1 nwname=2 wname=[ "Documentation", "x" ] } +< Rwalk { tag=0 nwqid=2 wqid=[ { type=(DIR) vers=1 path=2 }, { type=(0) vers=1 path=3 } ] } > Topen { tag=0 fid=1 mode=(MODE_READ) } < Ropen { tag=0 qid={ type=(0) vers=1 path=3 } iounit=0 } > Tread { tag=0 fid=1 offset=0 count=4096 } @@ -80,24 +80,24 @@ < Rclunk { tag=0 } > Tversion { tag=NOTAG max_msg_size=8192 version="9P2000" } < Rversion { tag=NOTAG max_msg_size=4120 version="9P2000" } -> Tauth { tag=0 afid=0 uname="lukeshu" aname="" n_uid=0 } -< Rerror { tag=0 errstr="authentication not required" errnum=95 } -> Tattach { tag=0 fid=0 afid=NOFID uname="lukeshu" aname="" n_uid=0 } +> Tauth { tag=0 afid=0 uname="nobody" aname="" n_uid=0 } +< Rerror { tag=0 errstr="authentication not required" errnum=L_EOPNOTSUPP } +> Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" n_uid=0 } < Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } -> Twalk { tag=0 fid=0 newfid=1 nwname=2 wname=["Documentation", "x" ] } -< Rwalk { tag=0 nwqid=2 wqid=[{ type=(DIR) vers=1 path=2 }, { type=(0) vers=1 path=3 } ] } +> Twalk { tag=0 fid=0 newfid=1 nwname=2 wname=[ "Documentation", "x" ] } +< Rwalk { tag=0 nwqid=2 wqid=[ { type=(DIR) vers=1 path=2 }, { type=(0) vers=1 path=3 } ] } > Tstat { tag=0 fid=1 } < Rstat { tag=0 stat={ kern_type=0 kern_dev=0 file_qid={ type=(0) vers=1 path=3 } file_mode=(0444) file_atime=1728337905 file_mtime=1728337904 file_size=166 file_name="x" file_owner_uid="root" file_owner_gid="root" file_last_modified_uid="root" file_extension="" file_owner_n_uid=0 file_owner_n_gid=0 file_last_modified_n_uid=0 } } > Tclunk { tag=0 fid=1 } < Rclunk { tag=0 } > Tversion { tag=NOTAG max_msg_size=8192 version="9P2000" } < Rversion { tag=NOTAG max_msg_size=4120 version="9P2000" } -> Tauth { tag=0 afid=0 uname="lukeshu" aname="" n_uid=0 } -< Rerror { tag=0 errstr="authentication not required" errnum=95 } -> Tattach { tag=0 fid=0 afid=NOFID uname="lukeshu" aname="" n_uid=0 } +> Tauth { tag=0 afid=0 uname="nobody" aname="" n_uid=0 } +< Rerror { tag=0 errstr="authentication not required" errnum=L_EOPNOTSUPP } +> Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" n_uid=0 } < Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } -> Twalk { tag=0 fid=0 newfid=1 nwname=1 wname=["shutdown" ] } -< Rwalk { tag=0 nwqid=1 wqid=[{ type=(0) vers=1 path=5 } ] } +> Twalk { tag=0 fid=0 newfid=1 nwname=1 wname=[ "shutdown" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=5 } ] } > Topen { tag=0 fid=1 mode=(TRUNC|MODE_WRITE) } < Ropen { tag=0 qid={ type=(0) vers=1 path=5 } iounit=0 } > Twrite { tag=0 fid=1 offset=0 count=2 data="1\n" } diff --git a/lib9p/tests/testclient-sess.c b/lib9p/tests/testclient-sess.c index 423dc2c..561c0c9 100644 --- a/lib9p/tests/testclient-sess.c +++ b/lib9p/tests/testclient-sess.c @@ -15,7 +15,7 @@ #include <libmisc/assert.h> #include <libmisc/endian.h> -#include <lib9p/9p.h> +#include <lib9p/core.h> #define MAX_MSG_SIZE (8*1024) @@ -91,12 +91,78 @@ int main(int argc, char *argv[]) { recv9p(); /* Rversion */ ctx.version = LIB9P_VER_9P2000_u; - /* ext version ********************************************************/ - send9p(Tversion, .tag=0, .max_msg_size=57, .version=lib9p_str("9P2000.u")); + /* ext version, users *************************************************/ + send9p(Tversion, .tag=0, .max_msg_size=(8*1024), .version=lib9p_str("9P2000.u")); recv9p(); /* Rversion */ ctx.version = LIB9P_VER_9P2000_u; + send9p(Tattach, .tag=0, .fid=0, .afid=LIB9P_FID_NOFID, .uname=lib9p_str("alice"), .n_uid=1000, .aname=lib9p_str("")); + recv9p(); /* Rattach */ + send9p(Tattach, .tag=0, .fid=1, .afid=LIB9P_FID_NOFID, .uname=lib9p_str("bob"), .n_uid=1001, .aname=lib9p_str("")); + recv9p(); /* Rattach */ + wname[0] = lib9p_str("whoami"); send9p(Twalk, .tag=0, .fid=0, .newfid=2, .nwname=1, .wname=wname); + recv9p(); /* Rwalk */ + wname[0] = lib9p_str("whoami"); send9p(Twalk, .tag=0, .fid=1, .newfid=3, .nwname=1, .wname=wname); + recv9p(); /* Rwalk */ + send9p(Topen, .tag=0, .fid=2, .mode=LIB9P_O_MODE_READ); + recv9p(); /* Ropen */ + send9p(Topen, .tag=0, .fid=3, .mode=LIB9P_O_MODE_READ); + recv9p(); /* Ropen */ + send9p(Tread, .tag=0, .fid=2, .offset=0, .count=100); + recv9p(); /* Rread */ + send9p(Tread, .tag=0, .fid=3, .offset=0, .count=100); + recv9p(); /* Rread */ + + /* walk ***************************************************************/ + send9p(Tversion, .tag=0, .max_msg_size=(8*1024), .version=lib9p_str("9P2000")); + recv9p(); /* Rversion */ + ctx.version = LIB9P_VER_9P2000; + send9p(Tattach, .tag=0, .fid=0, .afid=LIB9P_FID_NOFID, .uname=lib9p_str("nobody"), .aname=lib9p_str("")); + recv9p(); /* Rattach */ + + /* dup */ + send9p(Twalk, .tag=0, .fid=0, .newfid=1, .nwname=0); + recv9p(); /* Rwalk */ + + /* "The walk request carries as arguments an existing fid"... */ + send9p(Twalk, .tag=0, .fid=2, .newfid=3, .nwname=0); + recv9p(); /* Rerror */ + + /* ..."and a proposed newfid"... */ + send9p(Twalk, .tag=0, .fid=1, .newfid=0xffffffff, .nwname=0); + recv9p(); /* Rerror */ + + /* ..."(which must not be in use"... */ + send9p(Twalk, .tag=0, .fid=1, .newfid=0, .nwname=0); + recv9p(); /* Rerror */ + + /* ..."unless it is the same as fid)"... */ + send9p(Twalk, .tag=0, .fid=1, .newfid=1, .nwname=0); + recv9p(); /* Rwalk */ + + /* ... "that the client wishes to associate with the result of + * traversing the directory hierarchy by `walking' the heierarchy using + * the successive path name elements wname."... */ - /* main session *******************************************************/ + /* ..."The fid must represent a directory"... */ + wname[0] = lib9p_str("README.md"); send9p(Twalk, .tag=0, .fid=1, .newfid=2, .nwname=1, .wname=wname); + recv9p(); /* Rwalk */ + wname[0] = lib9p_str(".."); send9p(Twalk, .tag=0, .fid=2, .newfid=3, .nwname=1, .wname=wname); + recv9p(); /* Rerror */ + + /* ..."unless zero path name elements are specified." */ + send9p(Twalk, .tag=0, .fid=2, .newfid=3, .nwname=0); + recv9p(); /* Rwalk */ + + /* "The fid must be valid in the current session" (tested above)... */ + + /* ..."and must not have been opened for I/O by an open or create + * message."... */ + send9p(Topen, .tag=0, .fid=3, .mode=LIB9P_O_MODE_READ); + recv9p(); /* Ropen */ + send9p(Twalk, .tag=0, .fid=3, .newfid=4, .nwname=0); + recv9p(); /* Rerror */ + + /* flush **************************************************************/ send9p(Tversion, .tag=0, .max_msg_size=(8*1024), .version=lib9p_str("9P2000")); recv9p(); /* Rversion */ ctx.version = LIB9P_VER_9P2000; @@ -104,29 +170,62 @@ int main(int argc, char *argv[]) { recv9p(); /* Rattach */ /* flush, but original response comes back first */ - wname[0] = lib9p_str("slowread"); send9p(Twalk, .tag=0, .fid=0, .newfid=1, .nwname=1, .wname=wname); + wname[0] = lib9p_str("flush-read"); send9p(Twalk, .tag=0, .fid=0, .newfid=1, .nwname=1, .wname=wname); recv9p(); /* Rwalk */ send9p(Topen, .tag=0, .fid=1, .mode=LIB9P_O_MODE_READ); recv9p(); /* Ropen */ - send9p(Tread, .tag=1, .fid=1, .offset=0, .count=6); - send9p(Tflush, .tag=2, .oldtag=1); + send9p(Tread, .tag=0, .fid=1, .offset=0, .count=10); + send9p(Tflush, .tag=1, .oldtag=0); recv9p(); /* Rread */ recv9p(); /* Rflush */ /* flush, original request is aborted with error */ - wname[0] = lib9p_str("slowread-flushable"); send9p(Twalk, .tag=1, .fid=0, .newfid=2, .nwname=1, .wname=wname); + wname[0] = lib9p_str("flush-error"); send9p(Twalk, .tag=0, .fid=0, .newfid=2, .nwname=1, .wname=wname); recv9p(); /* Rwalk */ send9p(Topen, .tag=0, .fid=2, .mode=LIB9P_O_MODE_READ); recv9p(); /* Ropen */ - send9p(Tread, .tag=1, .fid=2, .offset=0, .count=6); - send9p(Tflush, .tag=2, .oldtag=1); + send9p(Tread, .tag=0, .fid=2, .offset=0, .count=10); + send9p(Tflush, .tag=1, .oldtag=0); recv9p(); /* Rerror */ recv9p(); /* Rflush */ + /* flush, original request is aborted without error */ + wname[0] = lib9p_str("flush-silent"); send9p(Twalk, .tag=0, .fid=0, .newfid=3, .nwname=1, .wname=wname); + recv9p(); /* Rwalk */ + send9p(Topen, .tag=0, .fid=3, .mode=LIB9P_O_MODE_READ); + recv9p(); /* Ropen */ + send9p(Tread, .tag=0, .fid=3, .offset=0, .count=10); + send9p(Tflush, .tag=1, .oldtag=0); + recv9p(); /* Rflush */ + + /* multiflush, original request is aborted without error */ + wname[0] = lib9p_str("flush-slowsilent"); send9p(Twalk, .tag=0, .fid=0, .newfid=4, .nwname=1, .wname=wname); + recv9p(); /* Rwalk */ + send9p(Topen, .tag=0, .fid=4, .mode=LIB9P_O_MODE_READ); + recv9p(); /* Ropen */ + send9p(Tread, .tag=0, .fid=4, .offset=0, .count=10); + send9p(Tflush, .tag=1, .oldtag=0); + send9p(Tflush, .tag=2, .oldtag=0); + recv9p(); /* Rflush */ + + /* flush, but flush is flushed */ + wname[0] = lib9p_str("flush-slowread"); send9p(Twalk, .tag=0, .fid=0, .newfid=5, .nwname=1, .wname=wname); + recv9p(); /* Rwalk */ + send9p(Topen, .tag=0, .fid=5, .mode=LIB9P_O_MODE_READ); + recv9p(); /* Ropen */ + send9p(Tread, .tag=0, .fid=5, .offset=0, .count=10); + send9p(Tflush, .tag=1, .oldtag=0); + send9p(Tflush, .tag=2, .oldtag=1); + recv9p(); /* Rflush */ + recv9p(); /* Rread */ + /* flush, unknown tag */ send9p(Tflush, .tag=0, .oldtag=99); recv9p(); /* Rflush */ + /* flushed by Tversion */ + send9p(Tread, .tag=0, .fid=3, .offset=0, .count=10); + /* shutdown ***********************************************************/ send9p(Tversion, .tag=0, .max_msg_size=(8*1024), .version=lib9p_str("9P2000")); recv9p(); /* Rversion */ diff --git a/lib9p/tests/testclient-sess.explog b/lib9p/tests/testclient-sess.explog index b1f3085..74a2cd7 100644 --- a/lib9p/tests/testclient-sess.explog +++ b/lib9p/tests/testclient-sess.explog @@ -11,47 +11,145 @@ > Tversion { tag=0 max_msg_size=57 version="9P2025.u" } < Rversion { tag=0 max_msg_size=57 version="9P2000.u" } -# ext version ################################################################## -> Tversion { tag=0 max_msg_size=57 version="9P2000.u" } -< Rversion { tag=0 max_msg_size=57 version="9P2000.u" } +# ext version, users ########################################################### +> Tversion { tag=0 max_msg_size=8192 version="9P2000.u" } +< Rversion { tag=0 max_msg_size=4120 version="9P2000.u" } +> Tattach { tag=0 fid=0 afid=NOFID uname="alice" aname="" n_uid=1000 } +< Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } +> Tattach { tag=0 fid=1 afid=NOFID uname="bob" aname="" n_uid=1001 } +< Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } +> Twalk { tag=0 fid=0 newfid=2 nwname=1 wname=[ "whoami" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=8 } ] } +> Twalk { tag=0 fid=1 newfid=3 nwname=1 wname=[ "whoami" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=8 } ] } +> Topen { tag=0 fid=2 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(0) vers=1 path=8 } iounit=0 } +> Topen { tag=0 fid=3 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(0) vers=1 path=8 } iounit=0 } +> Tread { tag=0 fid=2 offset=0 count=100 } +< Rread { tag=0 count=11 data="1000 alice\n" } +> Tread { tag=0 fid=3 offset=0 count=100 } +< Rread { tag=0 count=9 data="1001 bob\n" } + +# walk ######################################################################### +> Tversion { tag=0 max_msg_size=8192 version="9P2000" } +< Rversion { tag=0 max_msg_size=4120 version="9P2000" } +> Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" n_uid=0 } +< Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } + +# dup +> Twalk { tag=0 fid=0 newfid=1 nwname=0 wname=[ ] } +< Rwalk { tag=0 nwqid=0 wqid=[ ] } + +# "The walk request carries as arguments an existing fid"... +> Twalk { tag=0 fid=2 newfid=3 nwname=0 wname=[ ] } +< Rerror { tag=0 errstr="bad file number 2" errnum=L_EBADF } + +# ..."and a proposed newfid"... +> Twalk { tag=0 fid=1 newfid=NOFID nwname=0 wname=[ ] } +< Rerror { tag=0 errstr="cannot assign to NOFID" errnum=L_EBADF } + +# ..."(which must not be in use"... +> Twalk { tag=0 fid=1 newfid=0 nwname=0 wname=[ ] } +< Rerror { tag=0 errstr="FID already in use" errnum=L_EBADF } -# main session ################################################################# +# ..."unless it is the same as fid)"... +> Twalk { tag=0 fid=1 newfid=1 nwname=0 wname=[ ] } +< Rwalk { tag=0 nwqid=0 wqid=[ ] } + +# ... "that the client wishes to associate with the result of +# traversing the directory hierarchy by `walking' the heierarchy using +# the successive path name elements wname."... + +# ..."The fid must represent a directory"... +> Twalk { tag=0 fid=1 newfid=2 nwname=1 wname=[ "README.md" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=4 } ] } +> Twalk { tag=0 fid=2 newfid=3 nwname=1 wname=[ ".." ] } +< Rerror { tag=0 errstr="not a directory" errnum=L_ENOTDIR } + +# ..."unless zero path name elements are specified." +> Twalk { tag=0 fid=2 newfid=3 nwname=0 wname=[ ] } +< Rwalk { tag=0 nwqid=0 wqid=[ ] } + +# "The fid must be valid in the current session" (tested above)... + +# ..."and must not have been opened for I/O by an open or create +# message."... +> Topen { tag=0 fid=3 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(0) vers=1 path=4 } iounit=0 } +> Twalk { tag=0 fid=3 newfid=4 nwname=0 wname=[ ] } +< Rerror { tag=0 errstr="cannot walk on FID open for I/O" errnum=L_EALREADY } + +# flush ######################################################################## > Tversion { tag=0 max_msg_size=8192 version="9P2000" } < Rversion { tag=0 max_msg_size=4120 version="9P2000" } > Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" n_uid=0 } < Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } # flush, but original response comes back first -> Twalk { tag=0 fid=0 newfid=1 nwname=1 wname=["slowread" ] } -< Rwalk { tag=0 nwqid=1 wqid=[{ type=(0) vers=1 path=6 } ] } +> Twalk { tag=0 fid=0 newfid=1 nwname=1 wname=[ "flush-read" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=9 } ] } > Topen { tag=0 fid=1 mode=(MODE_READ) } -< Ropen { tag=0 qid={ type=(0) vers=1 path=6 } iounit=0 } -> Tread { tag=1 fid=1 offset=0 count=6 } -> Tflush { tag=2 oldtag=1 } -< Rread { tag=1 count=6 data="Sloth\n" } -< Rflush { tag=2 } +< Ropen { tag=0 qid={ type=(0) vers=1 path=9 } iounit=0 } +> Tread { tag=0 fid=1 offset=0 count=10 } +> Tflush { tag=1 oldtag=0 } +< Rread { tag=0 count=6 data="Sloth\n" } +< Rflush { tag=1 } -# flush, succeeds -> Twalk { tag=1 fid=0 newfid=2 nwname=1 wname=["slowread-flushable" ] } -< Rwalk { tag=1 nwqid=1 wqid=[{ type=(0) vers=1 path=7 } ] } +# flush, original request is aborted with error +> Twalk { tag=0 fid=0 newfid=2 nwname=1 wname=[ "flush-error" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=10 } ] } > Topen { tag=0 fid=2 mode=(MODE_READ) } -< Ropen { tag=0 qid={ type=(0) vers=1 path=7 } iounit=0 } -> Tread { tag=1 fid=2 offset=0 count=6 } +< Ropen { tag=0 qid={ type=(0) vers=1 path=10 } iounit=0 } +> Tread { tag=0 fid=2 offset=0 count=10 } +> Tflush { tag=1 oldtag=0 } +< Rerror { tag=0 errstr="request canceled by flush" errnum=L_ECANCELED } +< Rflush { tag=1 } + +# flush, original request is aborted without error +> Twalk { tag=0 fid=0 newfid=3 nwname=1 wname=[ "flush-silent" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=11 } ] } +> Topen { tag=0 fid=3 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(0) vers=1 path=11 } iounit=0 } +> Tread { tag=0 fid=3 offset=0 count=10 } +> Tflush { tag=1 oldtag=0 } +< Rflush { tag=1 } + +# multiflush, original request is aborted without error +> Twalk { tag=0 fid=0 newfid=4 nwname=1 wname=[ "flush-slowsilent" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=12 } ] } +> Topen { tag=0 fid=4 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(0) vers=1 path=12 } iounit=0 } +> Tread { tag=0 fid=4 offset=0 count=10 } +> Tflush { tag=1 oldtag=0 } +> Tflush { tag=2 oldtag=0 } +< Rflush { tag=2 } + +# flush, but flush is flushed +> Twalk { tag=0 fid=0 newfid=5 nwname=1 wname=[ "flush-slowread" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=13 } ] } +> Topen { tag=0 fid=5 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(0) vers=1 path=13 } iounit=0 } +> Tread { tag=0 fid=5 offset=0 count=10 } +> Tflush { tag=1 oldtag=0 } > Tflush { tag=2 oldtag=1 } < Rflush { tag=2 } -< Rerror { tag=1 errstr="request canceled by flush" errnum=125 } +< Rread { tag=0 count=6 data="Sloth\n" } # flush, unknown tag > Tflush { tag=0 oldtag=99 } < Rflush { tag=0 } +# flushed by Tversion +> Tread { tag=0 fid=3 offset=0 count=10 } + # shutdown ##################################################################### > Tversion { tag=0 max_msg_size=8192 version="9P2000" } < Rversion { tag=0 max_msg_size=4120 version="9P2000" } > Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" n_uid=0 } < Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } -> Twalk { tag=0 fid=0 newfid=0 nwname=1 wname=["shutdown" ] } -< Rwalk { tag=0 nwqid=1 wqid=[{ type=(0) vers=1 path=5 } ] } +> Twalk { tag=0 fid=0 newfid=0 nwname=1 wname=[ "shutdown" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=5 } ] } > Topen { tag=0 fid=0 mode=(MODE_WRITE) } < Ropen { tag=0 qid={ type=(0) vers=1 path=5 } iounit=0 } > Twrite { tag=0 fid=0 offset=0 count=2 data="1\n" } |