summaryrefslogtreecommitdiff
path: root/lib9p
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p')
-rw-r--r--lib9p/include/lib9p/srv.h4
-rw-r--r--lib9p/map.h4
-rw-r--r--lib9p/srv.c44
3 files changed, 33 insertions, 19 deletions
diff --git a/lib9p/include/lib9p/srv.h b/lib9p/include/lib9p/srv.h
index d2ada62..6a6fed0 100644
--- a/lib9p/include/lib9p/srv.h
+++ b/lib9p/include/lib9p/srv.h
@@ -16,14 +16,14 @@ struct lib9p_srv_reqctx {
static inline bool flush_requested(struct lib9p_srv_reqctx *ctx) {
assert(ctx);
- return cr_chan_can_write(&ctx->_flushch);
+ return cr_chan_can_send(&ctx->_flushch);
}
static inline int acknowledge_flush(struct lib9p_srv_reqctx *ctx) {
assert(ctx);
assert(cr_chan_can_send(&ctx->_flushch));
lib9p_error(ctx->base, LINUX_ECANCELED, "request canceled by flush");
- cr_chan_send(&ctx->_flushch, true);
+ cr_chan_send(&ctx->_flushch, (bool)true);
return -1;
}
diff --git a/lib9p/map.h b/lib9p/map.h
index ea9cdb6..833f4f5 100644
--- a/lib9p/map.h
+++ b/lib9p/map.h
@@ -28,8 +28,8 @@
#define MAP_KV(TNAME) CAT3(_,TNAME,_kv)
#define MAP_METHOD(TNAME, MNAME) CAT3(TNAME,_,MNAME)
#define MAP_FOREACH(m, k, v) \
- for (size_t i = 0, typeof(m->items[0].key) k, typeof(&m->items[0].val) v; i < ARRAY_LEN(m->items); i++) \
- if ( ({ k = m->items[i].key; v = &m->items[i].val; m->items[i].set; }) )
+ for (size_t i = 0; i < ARRAY_LEN((m)->items); i++) \
+ if ( ({ k = (m)->items[i].key; v = &(m)->items[i].val; (m)->items[i].set; }) )
#endif
/* This implementation is just an array that we brute-force search
diff --git a/lib9p/srv.c b/lib9p/srv.c
index 3d990aa..9bfe19e 100644
--- a/lib9p/srv.c
+++ b/lib9p/srv.c
@@ -21,7 +21,7 @@
#define NAME reqmap
#define KEY_T uint32_t
-#define VAL_T struct lib9p_reqctx
+#define VAL_T struct lib9p_srv_reqctx
#define CAP CONFIG_9P_MAX_REQS
#include "map.h"
@@ -50,6 +50,7 @@ struct lib9p_sess {
uint32_t rerror_overhead;
/* mutable */
bool initialized;
+ bool closing;
struct reqmap reqs;
struct fidmap fids;
};
@@ -157,7 +158,6 @@ COROUTINE lib9p_srv_read_cr(void *_srv) {
.max_msg_size = CONFIG_9P_MAX_MSG_SIZE,
.rerror_overhead = initial_rerror_overhead,
.initialized = false,
- .refcount = 1,
};
for (;;) {
/* Read the message. */
@@ -190,15 +190,15 @@ COROUTINE lib9p_srv_read_cr(void *_srv) {
goto close;
/* Handle the message... in another coroutine. */
- sess.refcount++;
cr_chan_send(&srv->reqch, &req);
cr_pause_and_yield(); /* wait for it to have copied req */
}
close:
- netio_close(conn.fd, true, (--sess.refcount) == 0);
- if (sess.refcount) {
+ netio_close(conn.fd, true, sess.reqs.len == 0);
+ if (sess.reqs.len) {
+ sess.closing = true;
cr_pause_and_yield();
- assert(sess.refcount == 0);
+ assert(sess.reqs.len == 0);
netio_close(conn.fd, false, true);
}
}
@@ -244,7 +244,8 @@ COROUTINE lib9p_srv_write_cr(void *_srv) {
handle_Tmessage(&req);
- if ((--req.parent_sess->refcount) == 0)
+ reqmap_del(&req.parent_sess->reqs, req.tag);
+ if (req.parent_sess->closing && !req.parent_sess->reqs.len)
cr_unpause(req.parent_sess->parent_conn->reader);
}
@@ -327,14 +328,16 @@ static bool handle_Tmessage(struct lib9p_req *req) {
}
write:
- if (lib9p_ctx_has_error(&req->ctx))
+ if (lib9p_ctx_has_error(&req->ctx)) {
respond_error(req);
- else {
+ return true;
+ } else {
if (lib9p_marshal(&req->ctx, typ+1, req->tag, host_resp, req->net_bytes))
goto write;
cr_mutex_lock(&req->parent_sess->parent_conn->writelock);
netio_write(req->parent_sess->parent_conn->fd, req->net_bytes, decode_u32le(req->net_bytes));
cr_mutex_unlock(&req->parent_sess->parent_conn->writelock);
+ return false;
}
}
@@ -364,13 +367,24 @@ static void handle_Tversion(struct lib9p_req *ctx, struct lib9p_msg_Tversion *re
return;
}
-
- ctx->parent_sess--;
- MAP_FOREACH(&ctx->parent_sess->fids, fid, fptr) {
- fptr->vtable.free(subctx, fptr->impldata);
- fidmap_del(&ctx->parent_sess->fids, fid);
+ struct lib9p_srv_reqctx subctx = {
+ .base = &ctx->ctx,
+ };
+ if (ctx->parent_sess->reqs.len) {
+ ctx->parent_sess->closing = true;
+ // TODO: send flush events
+ cr_pause_and_yield();
+ assert(ctx->parent_sess->reqs.len == 0);
}
-}
+ if (ctx->parent_sess->fids.len) {
+ uint32_t fid;
+ struct lib9p_srv_file *fptr;
+ MAP_FOREACH(&ctx->parent_sess->fids, fid, fptr) {
+ fptr->vtable.free(&subctx, fptr->impldata);
+ fidmap_del(&ctx->parent_sess->fids, fid);
+ }
+ }
+ // TODO: replace session with a new one?
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"