summaryrefslogtreecommitdiff
path: root/lib9p/srv.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p/srv.c')
-rw-r--r--lib9p/srv.c107
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);