diff options
Diffstat (limited to 'lib9p/srv.c')
-rw-r--r-- | lib9p/srv.c | 107 |
1 files changed, 46 insertions, 61 deletions
diff --git a/lib9p/srv.c b/lib9p/srv.c index 1e52609..5660f08 100644 --- a/lib9p/srv.c +++ b/lib9p/srv.c @@ -19,6 +19,7 @@ #include <libcr_ipc/mutex.h> #include <libmisc/assert.h> #include <libmisc/endian.h> +#include <libmisc/map.h> #include <libhw/generic/net.h> #define LOG_NAME 9P_SRV @@ -79,12 +80,7 @@ struct srv_pathinfo { unsigned int io_refcount; }; -#define NAME pathmap -#define KEY_T srv_path_t -#define VAL_T struct srv_pathinfo -/* ( naive ) + ( working space for walk() ) */ -#define CAP ( (CONFIG_9P_SRV_MAX_FIDS*CONFIG_9P_SRV_MAX_DEPTH) + (CONFIG_9P_SRV_MAX_REQS*2) ) -#include "map.h" +MAP_DECLARE(pathmap, srv_path_t, struct srv_pathinfo); #define FIDFLAG_OPEN_R (1<<0) #define FIDFLAG_OPEN_W (1<<1) @@ -106,17 +102,8 @@ struct _srv_fidinfo { }; }; -#define NAME fidmap -#define KEY_T lib9p_fid_t -#define VAL_T struct _srv_fidinfo -#define CAP CONFIG_9P_SRV_MAX_FIDS -#include "map.h" - -#define NAME reqmap -#define KEY_T lib9p_tag_t -#define VAL_T struct _lib9p_srv_req * -#define CAP CONFIG_9P_SRV_MAX_REQS -#include "map.h" +MAP_DECLARE(fidmap, lib9p_fid_t, struct _srv_fidinfo); +MAP_DECLARE(reqmap, lib9p_tag_t, struct _lib9p_srv_req *); /* The hierarchy of concepts is: * @@ -330,15 +317,18 @@ void lib9p_srv_read(struct lib9p_srv *srv, lo_interface net_stream_conn _conn) { /* ...but usually in another coroutine. */ _lib9p_srv_reqch_send_req(&srv->_reqch, &req); } - if (sess.reqs.len == 0) + if (map_len(&sess.reqs) == 0) io_close(conn.fd); else { io_close_read(conn.fd); sess.closing = true; cr_pause_and_yield(); - assert(sess.reqs.len == 0); + assert(map_len(&sess.reqs) == 0); io_close_write(conn.fd); } + map_free(&sess.paths); + map_free(&sess.fids); + map_free(&sess.reqs); } /* write coroutine ************************************************************/ @@ -364,7 +354,8 @@ void lib9p_srv_worker_loop(struct lib9p_srv *srv) { * stack to our stack. */ req = *rpc_handle.req; /* Record that we have it. */ - reqmap_store(&req.parent_sess->reqs, req.tag, &req); + struct _lib9p_srv_req **reqpp = map_store(&req.parent_sess->reqs, req.tag, &req); + assert(reqpp && *reqpp == &req); /* Notify the reader coroutine that we're done with * its data. */ _lib9p_srv_reqch_send_resp(rpc_handle, 0); @@ -375,8 +366,8 @@ void lib9p_srv_worker_loop(struct lib9p_srv *srv) { /* Release resources. ****************************************/ while (_lib9p_srv_flushch_can_send(&req.ctx._flushch)) _lib9p_srv_flushch_send(&req.ctx._flushch, false); - reqmap_del(&req.parent_sess->reqs, req.tag); - if (req.parent_sess->closing && !req.parent_sess->reqs.len) + map_del(&req.parent_sess->reqs, req.tag); + if (req.parent_sess->closing && !map_len(&req.parent_sess->reqs)) cr_unpause(req.parent_sess->parent_conn->reader); } } @@ -494,11 +485,11 @@ static inline struct srv_pathinfo *srv_util_pathsave(struct _lib9p_srv_req *ctx, assert(!LO_IS_NULL(file)); struct lib9p_qid qid = LO_CALL(file, qid); - struct srv_pathinfo *pathinfo = pathmap_load(&ctx->parent_sess->paths, qid.path); + struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, qid.path); if (pathinfo) assert(LO_EQ(pathinfo->file, file)); else { - pathinfo = pathmap_store(&ctx->parent_sess->paths, qid.path, + pathinfo = map_store(&ctx->parent_sess->paths, qid.path, (struct srv_pathinfo){ .file = file, .parent_dir = parent_path, @@ -507,7 +498,7 @@ static inline struct srv_pathinfo *srv_util_pathsave(struct _lib9p_srv_req *ctx, }); assert(pathinfo); if (parent_path != qid.path) { - struct srv_pathinfo *parent = pathmap_load(&ctx->parent_sess->paths, parent_path); + struct srv_pathinfo *parent = map_load(&ctx->parent_sess->paths, parent_path); assert(parent); parent->gc_refcount++; } @@ -523,14 +514,14 @@ static inline struct srv_pathinfo *srv_util_pathsave(struct _lib9p_srv_req *ctx, static inline void srv_util_pathfree(struct _lib9p_srv_req *ctx, srv_path_t path) { assert(ctx); - struct srv_pathinfo *pathinfo = pathmap_load(&ctx->parent_sess->paths, path); + struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, path); assert(pathinfo); pathinfo->gc_refcount--; if (pathinfo->gc_refcount == 0) { if (pathinfo->parent_dir != path) srv_util_pathfree(ctx, pathinfo->parent_dir); LO_CALL(pathinfo->file, free); - pathmap_del(&ctx->parent_sess->paths, path); + map_del(&ctx->parent_sess->paths, path); } } @@ -548,13 +539,14 @@ static inline struct _srv_fidinfo *srv_util_fidsave(struct _lib9p_srv_req *ctx, assert(ctx); assert(fid != LIB9P_FID_NOFID); assert(pathinfo); + infof("pathinfo=%p", pathinfo); struct lib9p_qid qid = LO_CALL(pathinfo->file, qid); - struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, fid); + struct _srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, fid); if (fidinfo) { if (overwrite) { - struct srv_pathinfo *old_pathinfo = pathmap_load(&ctx->parent_sess->paths, fidinfo->path); + struct srv_pathinfo *old_pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); assert(old_pathinfo); if (srv_util_pathisdir(old_pathinfo)) { if (!LO_IS_NULL(fidinfo->dir.io)) @@ -570,12 +562,8 @@ static inline struct _srv_fidinfo *srv_util_fidsave(struct _lib9p_srv_req *ctx, return NULL; } } else { - fidinfo = fidmap_store(&ctx->parent_sess->fids, fid, (struct _srv_fidinfo){}); - if (!fidinfo) { - lib9p_error(&ctx->ctx.basectx, - LINUX_EMFILE, "too many open files"); - return NULL; - } + fidinfo = map_store(&ctx->parent_sess->fids, fid, (struct _srv_fidinfo){}); + assert(fidinfo); } *fidinfo = (struct _srv_fidinfo){ .path = qid.path, @@ -624,25 +612,22 @@ static void handle_Tversion(struct _lib9p_srv_req *ctx, : req->max_msg_size; /* Close the old session. */ - if (ctx->parent_sess->reqs.len) { + if (map_len(&ctx->parent_sess->reqs)) { /* Flush all in-progress requests, and wait for them * to finish. */ - struct cr_select_arg *list = alloca(sizeof(struct cr_select_arg) * ctx->parent_sess->reqs.len); - while (ctx->parent_sess->reqs.len) { - uint16_t tag [[gnu::unused]]; - struct _lib9p_srv_req **reqpp; + struct cr_select_arg *list = alloca(sizeof(struct cr_select_arg) * map_len(&ctx->parent_sess->reqs)); + while (map_len(&ctx->parent_sess->reqs)) { size_t i = 0; bool flushed; MAP_FOREACH(&ctx->parent_sess->reqs, tag, reqpp) { list[i] = CR_SELECT_RECV(&((*reqpp)->ctx._flushch), &flushed); } + assert(i == map_len(&ctx->parent_sess->reqs)); cr_select_v(i, list); } } - if (ctx->parent_sess->fids.len) { + if (map_len(&ctx->parent_sess->fids)) { /* Close all FIDs. */ - uint32_t fid; - struct _srv_fidinfo *fidinfo [[gnu::unused]]; MAP_FOREACH(&ctx->parent_sess->fids, fid, fidinfo) { handle_Tclunk(ctx, &(struct lib9p_msg_Tclunk){.fid = fid}, @@ -687,7 +672,7 @@ static void handle_Tattach(struct _lib9p_srv_req *ctx, if (srv->auth) { /* - struct lib9p_srv_filehandle *fh = fidmap_get(req->afid); + struct lib9p_srv_filehandle *fh = map_get(req->afid); if (!fh) lib9p_error(&ctx->ctx.basectx, LINUX_EACCES, "FID provided as auth-file is not a valid FID"); @@ -755,7 +740,7 @@ static void handle_Tflush(struct _lib9p_srv_req *ctx, struct lib9p_msg_Rflush *resp) { util_handler_common(ctx, req, resp); - struct _lib9p_srv_req **oldreqp = reqmap_load(&ctx->parent_sess->reqs, req->oldtag); + struct _lib9p_srv_req **oldreqp = map_load(&ctx->parent_sess->reqs, req->oldtag); if (oldreqp) _lib9p_srv_flushch_recv(&((*oldreqp)->ctx._flushch)); } @@ -771,14 +756,14 @@ static void handle_Twalk(struct _lib9p_srv_req *ctx, return; } - struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, req->fid); + struct _srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { lib9p_errorf(&ctx->ctx.basectx, LINUX_EBADF, "bad file number %"PRIu32, req->fid); return; } - struct srv_pathinfo *pathinfo = pathmap_load(&ctx->parent_sess->paths, fidinfo->path); + struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); assert(pathinfo); pathinfo->gc_refcount++; @@ -786,7 +771,7 @@ static void handle_Twalk(struct _lib9p_srv_req *ctx, for (resp->nwqid = 0; resp->nwqid < req->nwname; resp->nwqid++) { struct srv_pathinfo *new_pathinfo; if (lib9p_str_eq(req->wname[resp->nwqid], lib9p_str(".."))) { - new_pathinfo = pathmap_load(&ctx->parent_sess->paths, pathinfo->parent_dir); + new_pathinfo = map_load(&ctx->parent_sess->paths, pathinfo->parent_dir); assert(new_pathinfo); new_pathinfo->gc_refcount++; } else { @@ -838,7 +823,7 @@ static void handle_Topen(struct _lib9p_srv_req *ctx, util_handler_common(ctx, req, resp); /* Check that the FID is valid for this. */ - struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, req->fid); + struct _srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { lib9p_errorf(&ctx->ctx.basectx, LINUX_EBADF, "bad file number %"PRIu32, req->fid); @@ -849,7 +834,7 @@ static void handle_Topen(struct _lib9p_srv_req *ctx, LINUX_EALREADY, "FID is already open"); return; } - struct srv_pathinfo *pathinfo = pathmap_load(&ctx->parent_sess->paths, fidinfo->path); + struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); assert(pathinfo); if (srv_util_pathisdir(pathinfo)) { if ( ((req->mode & LIB9P_O_MODE_MASK) != LIB9P_O_MODE_READ) || @@ -867,7 +852,7 @@ static void handle_Topen(struct _lib9p_srv_req *ctx, /* Check permissions. */ if (reqmode & LIB9P_O_RCLOSE) { - struct srv_pathinfo *parent = pathmap_load(&ctx->parent_sess->paths, pathinfo->parent_dir); + struct srv_pathinfo *parent = map_load(&ctx->parent_sess->paths, pathinfo->parent_dir); assert(parent); struct lib9p_stat parent_stat = LO_CALL(parent->file, stat, &ctx->ctx); if (lib9p_ctx_has_error(&ctx->ctx.basectx)) @@ -968,7 +953,7 @@ static void handle_Tread(struct _lib9p_srv_req *ctx, /* TODO: serialize simultaneous reads to the same FID */ /* Check that the FID is valid for this. */ - struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, req->fid); + struct _srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { lib9p_errorf(&ctx->ctx.basectx, LINUX_EBADF, "bad file number %"PRIu32, req->fid); @@ -981,7 +966,7 @@ static void handle_Tread(struct _lib9p_srv_req *ctx, } /* Variables. */ - struct srv_pathinfo *pathinfo = pathmap_load(&ctx->parent_sess->paths, fidinfo->path); + struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); assert(pathinfo); /* Do it. */ @@ -1032,7 +1017,7 @@ static void handle_Twrite(struct _lib9p_srv_req *ctx, /* TODO: serialize simultaneous writes to the same FID */ /* Check that the FID is valid for this. */ - struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, req->fid); + struct _srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { lib9p_errorf(&ctx->ctx.basectx, LINUX_EBADF, "bad file number %"PRIu32, req->fid); @@ -1045,7 +1030,7 @@ static void handle_Twrite(struct _lib9p_srv_req *ctx, } /* Variables. */ - struct srv_pathinfo *pathinfo = pathmap_load(&ctx->parent_sess->paths, fidinfo->path); + struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); assert(pathinfo); /* Do it. */ @@ -1053,7 +1038,7 @@ static void handle_Twrite(struct _lib9p_srv_req *ctx, } static void clunkremove(struct _lib9p_srv_req *ctx, lib9p_fid_t fid, bool remove) { - struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, fid); + struct _srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, fid); if (!fidinfo) { lib9p_errorf(&ctx->ctx.basectx, LINUX_EBADF, "bad file number %"PRIu32, fid); @@ -1061,7 +1046,7 @@ static void clunkremove(struct _lib9p_srv_req *ctx, lib9p_fid_t fid, bool remove } if (fidinfo->flags & FIDFLAG_RCLOSE) remove = true; - struct srv_pathinfo *pathinfo = pathmap_load(&ctx->parent_sess->paths, fidinfo->path); + struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); assert(pathinfo); if (remove) { @@ -1070,7 +1055,7 @@ static void clunkremove(struct _lib9p_srv_req *ctx, lib9p_fid_t fid, bool remove LINUX_EBUSY, "cannot remove root"); goto clunk; } - struct srv_pathinfo *parent = pathmap_load(&ctx->parent_sess->paths, pathinfo->parent_dir); + struct srv_pathinfo *parent = map_load(&ctx->parent_sess->paths, pathinfo->parent_dir); assert(parent); struct lib9p_stat parent_stat = LO_CALL(parent->file, stat, &ctx->ctx); if (!srv_util_check_perm(ctx, &parent_stat, 0b010)) { @@ -1090,7 +1075,7 @@ static void clunkremove(struct _lib9p_srv_req *ctx, lib9p_fid_t fid, bool remove pathinfo->io_refcount--; } srv_util_pathfree(ctx, LO_CALL(pathinfo->file, qid).path); - fidmap_del(&ctx->parent_sess->fids, fid); + map_del(&ctx->parent_sess->fids, fid); } static void handle_Tclunk(struct _lib9p_srv_req *ctx, @@ -1115,13 +1100,13 @@ static void handle_Tstat(struct _lib9p_srv_req *ctx, struct lib9p_msg_Rstat *resp) { util_handler_common(ctx, req, resp); - struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, req->fid); + struct _srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { lib9p_errorf(&ctx->ctx.basectx, LINUX_EBADF, "bad file number %"PRIu32, req->fid); return; } - struct srv_pathinfo *pathinfo = pathmap_load(&ctx->parent_sess->paths, fidinfo->path); + struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); assert(pathinfo); resp->stat = LO_CALL(pathinfo->file, stat, &ctx->ctx); |