|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [UNIKRAFT PATCH 1/7] lib/uk9p: Rewrite serialization
This patch rewrites serialization in a type-safe way: compiler can
issue warnings if the data types don't match. Previously the types
were hidden behind a va_list and thus unchecked.
Signed-off-by: Cristian Banu <cristb@xxxxxxxxx>
---
lib/9pfs/9pfs_vnops.c | 2 +-
lib/uk9p/9p.c | 302 ++++++++++++++++++++--------------
lib/uk9p/9pdev.c | 36 -----
lib/uk9p/9preq.c | 314 ++----------------------------------
lib/uk9p/exportsyms.uk | 7 -
lib/uk9p/include/uk/9pdev.h | 23 ---
lib/uk9p/include/uk/9preq.h | 239 ++++++++++++++++++++-------
7 files changed, 376 insertions(+), 547 deletions(-)
diff --git a/lib/9pfs/9pfs_vnops.c b/lib/9pfs/9pfs_vnops.c
index 5e6a7bb..6d3ece3 100644
--- a/lib/9pfs/9pfs_vnops.c
+++ b/lib/9pfs/9pfs_vnops.c
@@ -409,7 +409,7 @@ again:
fake_request.recv.size = fd->readdir_sz;
fake_request.recv.offset = fd->readdir_off;
fake_request.state = UK_9PREQ_RECEIVED;
- rc = uk_9preq_deserialize(&fake_request, "S", &stat);
+ rc = uk_9preq_readstat(&fake_request, &stat);
if (rc == -ENOBUFS) {
/*
diff --git a/lib/uk9p/9p.c b/lib/uk9p/9p.c
index eb4c2dc..638555b 100644
--- a/lib/uk9p/9p.c
+++ b/lib/uk9p/9p.c
@@ -40,28 +40,49 @@
#include <uk/9preq.h>
#include <uk/9pfid.h>
+static inline int send_and_wait_zc(struct uk_9pdev *dev, struct uk_9preq *req,
+ enum uk_9preq_zcdir zc_dir, void *zc_buf, uint32_t zc_size,
+ uint32_t zc_offset)
+{
+ int rc;
+
+ if ((rc = uk_9preq_ready(req, zc_dir, zc_buf, zc_size, zc_offset)) ||
+ (rc = uk_9pdev_request(dev, req)) ||
+ (rc = uk_9preq_waitreply(req)))
+ return rc;
+
+ return 0;
+}
+
+static inline int send_and_wait_no_zc(struct uk_9pdev *dev,
+ struct uk_9preq *req)
+{
+ return send_and_wait_zc(dev, req, UK_9PREQ_ZCDIR_NONE, NULL, 0, 0);
+}
+
struct uk_9preq *uk_9p_version(struct uk_9pdev *dev,
const char *requested, struct uk_9p_str *received)
{
struct uk_9p_str requested_str;
struct uk_9preq *req;
- int rc;
+ int rc = 0;
uint32_t new_msize;
uk_9p_str_init(&requested_str, requested);
- uk_pr_debug("TVERSION msize %u version %s\n",
- dev->msize, requested);
-
- req = uk_9pdev_call(dev, UK_9P_TVERSION, __PAGE_SIZE, "ds",
- dev->msize, &requested_str);
+ req = uk_9pdev_req_create(dev, UK_9P_TVERSION, __PAGE_SIZE);
if (PTRISERR(req))
return req;
- rc = uk_9preq_deserialize(req, "ds", &new_msize, received);
+ uk_pr_debug("TVERSION msize %u version %s\n",
+ dev->msize, requested);
- if (rc)
- return ERR2PTR(rc);
+ if ((rc = uk_9preq_write32(req, dev->msize)) ||
+ (rc = uk_9preq_writestr(req, &requested_str)) ||
+ (rc = send_and_wait_no_zc(dev, req)) ||
+ (rc = uk_9preq_read32(req, &new_msize)) ||
+ (rc = uk_9preq_readstr(req, received)))
+ goto free;
uk_pr_debug("RVERSION msize %u version %.*s\n", new_msize,
received->size, received->data);
@@ -76,6 +97,10 @@ struct uk_9preq *uk_9p_version(struct uk_9pdev *dev,
uk_pr_debug("Invalid new message size.\n");
return req;
+
+free:
+ uk_9pdev_req_remove(dev, req);
+ return ERR2PTR(rc);
}
struct uk_9pfid *uk_9p_attach(struct uk_9pdev *dev, uint32_t afid,
@@ -94,43 +119,56 @@ struct uk_9pfid *uk_9p_attach(struct uk_9pdev *dev,
uint32_t afid,
if (PTRISERR(fid))
return fid;
- uk_pr_debug("TATTACH fid %u afid %u uname %s aname %s n_uname %u\n",
- fid->fid, afid, uname, aname, n_uname);
-
- req = uk_9pdev_call(dev, UK_9P_TATTACH, __PAGE_SIZE, "ddssd",
- fid->fid, afid, &uname_str, &aname_str, n_uname);
+ req = uk_9pdev_req_create(dev, UK_9P_TATTACH, __PAGE_SIZE);
if (PTRISERR(req)) {
uk_9pdev_fid_release(fid);
return (void *)req;
}
- rc = uk_9preq_deserialize(req, "Q", &fid->qid);
+ uk_pr_debug("TATTACH fid %u afid %u uname %s aname %s n_uname %u\n",
+ fid->fid, afid, uname, aname, n_uname);
+
+ rc = 0;
+ if ((rc = uk_9preq_write32(req, fid->fid)) ||
+ (rc = uk_9preq_write32(req, afid)) ||
+ (rc = uk_9preq_writestr(req, &uname_str)) ||
+ (rc = uk_9preq_writestr(req, &aname_str)) ||
+ (rc = uk_9preq_write32(req, n_uname)) ||
+ (rc = send_and_wait_no_zc(dev, req)) ||
+ (rc = uk_9preq_readqid(req, &fid->qid)))
+ goto free;
+
uk_9pdev_req_remove(dev, req);
uk_pr_debug("RATTACH qid type %u version %u path %lu\n",
fid->qid.type, fid->qid.version, fid->qid.path);
- if (rc < 0) {
- uk_9pdev_fid_release(fid);
- return ERR2PTR(rc);
- }
-
return fid;
+
+free:
+ uk_9pdev_fid_release(fid);
+ uk_9pdev_req_remove(dev, req);
+ return ERR2PTR(rc);
}
int uk_9p_flush(struct uk_9pdev *dev, uint16_t oldtag)
{
struct uk_9preq *req;
+ int rc = 0;
- uk_pr_debug("TFLUSH oldtag %u\n", oldtag);
- req = uk_9pdev_call(dev, UK_9P_TFLUSH, __PAGE_SIZE, "w", oldtag);
+ req = uk_9pdev_req_create(dev, UK_9P_TFLUSH, __PAGE_SIZE);
if (PTRISERR(req))
return PTR2ERR(req);
+ uk_pr_debug("TFLUSH oldtag %u\n", oldtag);
+ if ((rc = uk_9preq_write16(req, oldtag)) ||
+ (rc = send_and_wait_no_zc(dev, req)))
+ goto out;
uk_pr_debug("RFLUSH\n");
- uk_9pdev_req_remove(dev, req);
- return 0;
+out:
+ uk_9pdev_req_remove(dev, req);
+ return rc;
}
struct uk_9pfid *uk_9p_walk(struct uk_9pdev *dev, struct uk_9pfid *fid,
@@ -141,7 +179,7 @@ struct uk_9pfid *uk_9p_walk(struct uk_9pdev *dev, struct
uk_9pfid *fid,
struct uk_9p_str name_str;
uint16_t nwqid;
uint16_t nwname;
- int rc;
+ int rc = 0;
uk_9p_str_init(&name_str, name);
@@ -151,51 +189,56 @@ struct uk_9pfid *uk_9p_walk(struct uk_9pdev *dev, struct
uk_9pfid *fid,
nwname = name ? 1 : 0;
+ req = uk_9pdev_req_create(dev, UK_9P_TWALK, __PAGE_SIZE);
+ if (PTRISERR(req)) {
+ rc = PTR2ERR(req);
+ goto out;
+ }
+
if (name) {
uk_pr_debug("TWALK fid %u newfid %u nwname %d name %s\n",
fid->fid, newfid->fid, nwname, name);
- req = uk_9pdev_call(dev, UK_9P_TWALK, __PAGE_SIZE, "ddws",
- fid->fid, newfid->fid, nwname, &name_str);
+ if ((rc = uk_9preq_write32(req, fid->fid)) ||
+ (rc = uk_9preq_write32(req, newfid->fid)) ||
+ (rc = uk_9preq_write16(req, nwname)) ||
+ (rc = uk_9preq_writestr(req, &name_str)))
+ goto out;
} else {
uk_pr_debug("TWALK fid %u newfid %u nwname %d\n",
fid->fid, newfid->fid, nwname);
- req = uk_9pdev_call(dev, UK_9P_TWALK, __PAGE_SIZE, "ddw",
- fid->fid, newfid->fid, nwname);
+ if ((rc = uk_9preq_write32(req, fid->fid)) ||
+ (rc = uk_9preq_write32(req, newfid->fid)) ||
+ (rc = uk_9preq_write16(req, nwname)))
+ goto out;
}
- if (PTRISERR(req)) {
+ if ((rc = send_and_wait_no_zc(dev, req))) {
/*
* Don't clunk if request has finished with error, as the fid
* is invalid.
*/
newfid->was_removed = 1;
- rc = PTR2ERR(req);
goto out;
}
- rc = uk_9preq_deserialize(req, "w", &nwqid);
- if (rc < 0)
- goto out_req;
+ if ((rc = uk_9preq_read16(req, &nwqid)))
+ goto out;
uk_pr_debug("RWALK nwqid %u\n", nwqid);
if (nwqid != nwname) {
rc = -ENOENT;
- goto out_req;
+ goto out;
}
-
if (nwname) {
- rc = uk_9preq_deserialize(req, "Q", &newfid->qid);
- if (rc < 0)
- goto out_req;
+ if ((rc = uk_9preq_readqid(req, &newfid->qid)))
+ goto out;
} else
newfid->qid = fid->qid;
- rc = 0;
-out_req:
- uk_9pdev_req_remove(dev, req);
out:
+ uk_9pdev_req_remove(dev, req);
if (rc) {
uk_9pdev_fid_release(newfid);
return ERR2PTR(rc);
@@ -207,22 +250,27 @@ out:
int uk_9p_open(struct uk_9pdev *dev, struct uk_9pfid *fid, uint8_t mode)
{
struct uk_9preq *req;
- int rc;
-
- uk_pr_debug("TOPEN fid %u mode %u\n", fid->fid, mode);
+ int rc = 0;
- req = uk_9pdev_call(dev, UK_9P_TOPEN, __PAGE_SIZE, "db",
- fid->fid, mode);
+ req = uk_9pdev_req_create(dev, UK_9P_TOPEN, __PAGE_SIZE);
if (PTRISERR(req))
return PTR2ERR(req);
- rc = uk_9preq_deserialize(req, "Qd", &fid->qid, &fid->iounit);
- uk_9pdev_req_remove(dev, req);
+ uk_pr_debug("TOPEN fid %u mode %u\n", fid->fid, mode);
+
+ if ((rc = uk_9preq_write32(req, fid->fid)) ||
+ (rc = uk_9preq_write8(req, mode)) ||
+ (rc = send_and_wait_no_zc(dev, req)) ||
+ (rc = uk_9preq_readqid(req, &fid->qid)) ||
+ (rc = uk_9preq_read32(req, &fid->iounit)))
+ goto out;
uk_pr_debug("ROPEN qid type %u version %u path %lu iounit %u\n",
fid->qid.type, fid->qid.version, fid->qid.path,
fid->iounit);
+out:
+ uk_9pdev_req_remove(dev, req);
return rc;
}
@@ -233,63 +281,80 @@ int uk_9p_create(struct uk_9pdev *dev, struct uk_9pfid
*fid,
struct uk_9preq *req;
struct uk_9p_str name_str;
struct uk_9p_str extension_str;
- int rc;
+ int rc = 0;
uk_9p_str_init(&name_str, name);
uk_9p_str_init(&extension_str, extension);
- uk_pr_debug("TCREATE fid %u name %s perm %u mode %u ext %s\n",
- fid->fid, name, perm, mode, extension);
-
- req = uk_9pdev_call(dev, UK_9P_TCREATE, __PAGE_SIZE, "dsdbs",
- fid->fid, &name_str, perm, mode, &extension_str);
+ req = uk_9pdev_req_create(dev, UK_9P_TCREATE, __PAGE_SIZE);
if (PTRISERR(req))
return PTR2ERR(req);
- rc = uk_9preq_deserialize(req, "Qd", &fid->qid, &fid->iounit);
- uk_9pdev_req_remove(dev, req);
+ uk_pr_debug("TOPEN fid %u mode %u\n", fid->fid, mode);
+
+ if ((rc = uk_9preq_write32(req, fid->fid)) ||
+ (rc = uk_9preq_writestr(req, &name_str)) ||
+ (rc = uk_9preq_write32(req, perm)) ||
+ (rc = uk_9preq_write8(req, mode)) ||
+ (rc = uk_9preq_writestr(req, &extension_str)) ||
+ (rc = send_and_wait_no_zc(dev, req)) ||
+ (rc = uk_9preq_readqid(req, &fid->qid)) ||
+ (rc = uk_9preq_read32(req, &fid->iounit)))
+ goto out;
uk_pr_debug("RCREATE qid type %u version %u path %lu iounit %u\n",
fid->qid.type, fid->qid.version, fid->qid.path,
fid->iounit);
+out:
+ uk_9pdev_req_remove(dev, req);
return rc;
}
int uk_9p_remove(struct uk_9pdev *dev, struct uk_9pfid *fid)
{
struct uk_9preq *req;
+ int rc = 0;
/* The fid is considered invalid even if the remove fails. */
fid->was_removed = 1;
- uk_pr_debug("TREMOVE fid %u\n", fid->fid);
- req = uk_9pdev_call(dev, UK_9P_TREMOVE, __PAGE_SIZE, "d", fid->fid);
+ req = uk_9pdev_req_create(dev, UK_9P_TREMOVE, __PAGE_SIZE);
if (PTRISERR(req))
return PTR2ERR(req);
- uk_9pdev_req_remove(dev, req);
+ uk_pr_debug("TREMOVE fid %u\n", fid->fid);
+ if ((rc = uk_9preq_write32(req, fid->fid)) ||
+ (rc = send_and_wait_no_zc(dev, req)))
+ goto out;
uk_pr_debug("RREMOVE\n");
- return 0;
+out:
+ uk_9pdev_req_remove(dev, req);
+ return rc;
}
int uk_9p_clunk(struct uk_9pdev *dev, struct uk_9pfid *fid)
{
struct uk_9preq *req;
+ int rc = 0;
if (fid->was_removed)
return 0;
- uk_pr_debug("TCLUNK fid %u\n", fid->fid);
- req = uk_9pdev_call(dev, UK_9P_TCLUNK, __PAGE_SIZE, "d", fid->fid);
+ req = uk_9pdev_req_create(dev, UK_9P_TCLUNK, __PAGE_SIZE);
if (PTRISERR(req))
return PTR2ERR(req);
- uk_9pdev_req_remove(dev, req);
+ uk_pr_debug("TCLUNK fid %u\n", fid->fid);
+ if ((rc = uk_9preq_write32(req, fid->fid)) ||
+ (rc = send_and_wait_no_zc(dev, req)))
+ goto out;
uk_pr_debug("RCLUNK\n");
- return 0;
+out:
+ uk_9pdev_req_remove(dev, req);
+ return rc;
}
int64_t uk_9p_read(struct uk_9pdev *dev, struct uk_9pfid *fid,
@@ -309,24 +374,12 @@ int64_t uk_9p_read(struct uk_9pdev *dev, struct uk_9pfid
*fid,
if (PTRISERR(req))
return PTR2ERR(req);
- rc = uk_9preq_serialize(req, "dqd", fid->fid, offset, count);
- if (rc < 0)
- goto out;
-
- rc = uk_9preq_ready(req, UK_9PREQ_ZCDIR_READ, buf, count, 11);
- if (rc < 0)
- goto out;
-
- rc = uk_9pdev_request(dev, req);
- if (rc < 0)
- goto out;
-
- rc = uk_9preq_waitreply(req);
- if (rc < 0)
- goto out;
-
- rc = uk_9preq_deserialize(req, "d", &count);
- if (rc < 0)
+ if ((rc = uk_9preq_write32(req, fid->fid)) ||
+ (rc = uk_9preq_write64(req, offset)) ||
+ (rc = uk_9preq_write32(req, count)) ||
+ (rc = send_and_wait_zc(dev, req, UK_9PREQ_ZCDIR_READ, buf,
+ count, 11)) ||
+ (rc = uk_9preq_read32(req, &count)))
goto out;
uk_pr_debug("RREAD count %u\n", count);
@@ -353,24 +406,12 @@ int64_t uk_9p_write(struct uk_9pdev *dev, struct uk_9pfid
*fid,
if (PTRISERR(req))
return PTR2ERR(req);
- rc = uk_9preq_serialize(req, "dqd", fid->fid, offset, count);
- if (rc < 0)
- goto out;
-
- rc = uk_9preq_ready(req, UK_9PREQ_ZCDIR_WRITE, (void *)buf, count, 23);
- if (rc < 0)
- goto out;
-
- rc = uk_9pdev_request(dev, req);
- if (rc < 0)
- goto out;
-
- rc = uk_9preq_waitreply(req);
- if (rc < 0)
- goto out;
-
- rc = uk_9preq_deserialize(req, "d", &count);
- if (rc < 0)
+ if ((rc = uk_9preq_write32(req, fid->fid)) ||
+ (rc = uk_9preq_write64(req, offset)) ||
+ (rc = uk_9preq_write32(req, count)) ||
+ (rc = send_and_wait_zc(dev, req, UK_9PREQ_ZCDIR_WRITE,
+ (void *)buf, count, 23)) ||
+ (rc = uk_9preq_read32(req, &count)))
goto out;
uk_pr_debug("RWRITE count %u\n", count);
@@ -386,45 +427,58 @@ struct uk_9preq *uk_9p_stat(struct uk_9pdev *dev, struct
uk_9pfid *fid,
struct uk_9p_stat *stat)
{
struct uk_9preq *req;
- int rc;
+ int rc = 0;
uint16_t dummy;
- uk_pr_debug("TSTAT fid %u\n", fid->fid);
- req = uk_9pdev_call(dev, UK_9P_TSTAT, __PAGE_SIZE, "d", fid->fid);
+ req = uk_9pdev_req_create(dev, UK_9P_TSTAT, __PAGE_SIZE);
if (PTRISERR(req))
return req;
- rc = uk_9preq_deserialize(req, "wS", &dummy, stat);
- if (rc)
- return ERR2PTR(rc);
+ uk_pr_debug("TSTAT fid %u\n", fid->fid);
+
+ if ((rc = uk_9preq_write32(req, fid->fid)) ||
+ (rc = send_and_wait_no_zc(dev, req)) ||
+ (rc = uk_9preq_read16(req, &dummy)) ||
+ (rc = uk_9preq_readstat(req, stat)))
+ goto out;
+
uk_pr_debug("RSTAT\n");
return req;
+
+out:
+ uk_9pdev_req_remove(dev, req);
+ return ERR2PTR(rc);
}
int uk_9p_wstat(struct uk_9pdev *dev, struct uk_9pfid *fid,
struct uk_9p_stat *stat)
{
struct uk_9preq *req;
+ int rc = 0;
+ uint16_t *dummy;
- /*
- * The packed size of stat is 61 bytes + the size occupied by the
- * strings.
- */
- stat->size = 61;
- stat->size += stat->name.size;
- stat->size += stat->uid.size;
- stat->size += stat->gid.size;
- stat->size += stat->muid.size;
- stat->size += stat->extension.size;
-
- uk_pr_debug("TWSTAT fid %u\n", fid->fid);
- req = uk_9pdev_call(dev, UK_9P_TWSTAT, __PAGE_SIZE, "dwS", fid->fid,
- stat->size + 2, stat);
+ req = uk_9pdev_req_create(dev, UK_9P_TWSTAT, __PAGE_SIZE);
if (PTRISERR(req))
return PTR2ERR(req);
- uk_9pdev_req_remove(dev, req);
- uk_pr_debug("RWSTAT");
- return 0;
+ uk_pr_debug("TWSTAT fid %u\n", fid->fid);
+
+ if ((rc = uk_9preq_write32(req, fid->fid)))
+ goto out;
+
+ dummy = (uint16_t *)(req->xmit.buf + req->xmit.offset);
+ if ((rc = uk_9preq_write16(req, 0)) ||
+ (rc = uk_9preq_writestat(req, stat)))
+ goto out;
+ *dummy = stat->size + 2;
+
+ if ((rc = send_and_wait_no_zc(dev, req)))
+ goto out;
+
+ uk_pr_debug("RWSTAT\n");
+
+out:
+ uk_9pdev_req_remove(dev, req);
+ return rc;
}
diff --git a/lib/uk9p/9pdev.c b/lib/uk9p/9pdev.c
index 14ea7ca..1d7e09b 100644
--- a/lib/uk9p/9pdev.c
+++ b/lib/uk9p/9pdev.c
@@ -288,42 +288,6 @@ void uk_9pdev_xmit_notify(struct uk_9pdev *dev)
#endif
}
-struct uk_9preq *uk_9pdev_call(struct uk_9pdev *dev, uint8_t type,
- uint32_t size, const char *fmt, ...)
-{
- struct uk_9preq *req;
- va_list vl;
- int rc;
-
- req = uk_9pdev_req_create(dev, type, size);
- if (PTRISERR(req))
- return req;
-
- va_start(vl, fmt);
- rc = uk_9preq_vserialize(req, fmt, vl);
- va_end(vl);
-
- if (rc < 0)
- goto out;
-
- rc = uk_9preq_ready(req, UK_9PREQ_ZCDIR_NONE, NULL, 0, 0);
- if (rc < 0)
- goto out;
-
- rc = uk_9pdev_request(dev, req);
- if (rc < 0)
- goto out;
-
- rc = uk_9preq_waitreply(req);
- if (rc < 0)
- goto out;
-
- return req;
-out:
- uk_9pdev_req_remove(dev, req);
- return ERR2PTR(rc);
-}
-
struct uk_9preq *uk_9pdev_req_create(struct uk_9pdev *dev, uint8_t type,
uint32_t size)
{
diff --git a/lib/uk9p/9preq.c b/lib/uk9p/9preq.c
index 0fc4b1e..997f772 100644
--- a/lib/uk9p/9preq.c
+++ b/lib/uk9p/9preq.c
@@ -138,293 +138,6 @@ int uk_9preq_put(struct uk_9preq *req)
return last;
}
-static int _fcall_write(struct uk_9preq_fcall *fcall, const void *buf,
- uint32_t size)
-{
- if (fcall->offset + size > fcall->size)
- return -ENOBUFS;
-
- memcpy((char *)fcall->buf + fcall->offset, buf, size);
- fcall->offset += size;
- return 0;
-}
-
-static int _fcall_serialize(struct uk_9preq_fcall *f, const char *fmt, ...);
-
-static int _fcall_vserialize(struct uk_9preq_fcall *fcall, const char *fmt,
- va_list vl)
-{
- int rc = 0;
-
- while (*fmt) {
- switch (*fmt) {
- case 'b': {
- uint8_t x;
-
- x = va_arg(vl, unsigned int);
- rc = _fcall_write(fcall, &x, sizeof(x));
- if (rc < 0)
- goto out;
- break;
- }
- case 'w': {
- uint16_t x;
-
- x = va_arg(vl, unsigned int);
- rc = _fcall_write(fcall, &x, sizeof(x));
- if (rc < 0)
- goto out;
- break;
- }
- case 'd': {
- uint32_t x;
-
- x = va_arg(vl, uint32_t);
- rc = _fcall_write(fcall, &x, sizeof(x));
- if (rc < 0)
- goto out;
- break;
- }
- case 'q': {
- uint64_t x;
-
- x = va_arg(vl, uint64_t);
- rc = _fcall_write(fcall, &x, sizeof(x));
- if (rc < 0)
- goto out;
- break;
- }
- case 's': {
- struct uk_9p_str *p;
-
- p = va_arg(vl, struct uk_9p_str *);
- rc = _fcall_write(fcall, &p->size, sizeof(p->size));
- if (rc < 0)
- goto out;
- rc = _fcall_write(fcall, p->data, p->size);
- if (rc < 0)
- goto out;
- break;
- }
- case 'Q': {
- struct uk_9p_qid *p;
-
- p = va_arg(vl, struct uk_9p_qid *);
- rc = _fcall_serialize(fcall, "bdq", p->type,
- p->version, p->path);
- if (rc < 0)
- goto out;
- break;
- }
- case 'S': {
- struct uk_9p_stat *p;
-
- p = va_arg(vl, struct uk_9p_stat *);
- rc = _fcall_serialize(fcall, "wwdQdddqsssssddd",
- p->size, p->type, p->dev, &p->qid,
- p->mode, p->atime, p->mtime, p->length,
- &p->name, &p->uid, &p->gid, &p->muid,
- &p->extension, p->n_uid, p->n_gid,
- p->n_muid);
- if (rc < 0)
- goto out;
- break;
- }
- default:
- rc = -EINVAL;
- goto out;
- }
-
- fmt++;
- }
-
-out:
- return rc;
-}
-
-static int _fcall_serialize(struct uk_9preq_fcall *f, const char *fmt, ...)
-{
- va_list vl;
- int rc;
-
- va_start(vl, fmt);
- rc = _fcall_vserialize(f, fmt, vl);
- va_end(vl);
-
- return rc;
-}
-
-int uk_9preq_vserialize(struct uk_9preq *req, const char *fmt, va_list vl)
-{
- int rc;
-
- UK_ASSERT(req);
- UK_ASSERT(UK_READ_ONCE(req->state) == UK_9PREQ_INITIALIZED);
- rc = _fcall_vserialize(&req->xmit, fmt, vl);
-
- return rc;
-}
-
-int uk_9preq_serialize(struct uk_9preq *req, const char *fmt, ...)
-{
- va_list vl;
- int rc;
-
- va_start(vl, fmt);
- rc = uk_9preq_vserialize(req, fmt, vl);
- va_end(vl);
-
- return rc;
-}
-
-static int _fcall_read(struct uk_9preq_fcall *fcall, void *buf, uint32_t size)
-{
- if (fcall->offset + size > fcall->size)
- return -ENOBUFS;
-
- memcpy(buf, (char *)fcall->buf + fcall->offset, size);
- fcall->offset += size;
- return 0;
-}
-
-static int _fcall_deserialize(struct uk_9preq_fcall *f, const char *fmt, ...);
-
-static int _fcall_vdeserialize(struct uk_9preq_fcall *fcall,
- const char *fmt,
- va_list vl)
-{
- int rc = 0;
-
- while (*fmt) {
- switch (*fmt) {
- case 'b': {
- uint8_t *x;
-
- x = va_arg(vl, uint8_t *);
- rc = _fcall_read(fcall, x, sizeof(*x));
- if (rc < 0)
- goto out;
- break;
- }
- case 'w': {
- uint16_t *x;
-
- x = va_arg(vl, uint16_t *);
- rc = _fcall_read(fcall, x, sizeof(*x));
- if (rc < 0)
- goto out;
- break;
- }
- case 'd': {
- uint32_t *x;
-
- x = va_arg(vl, uint32_t *);
- rc = _fcall_read(fcall, x, sizeof(*x));
- if (rc < 0)
- goto out;
- break;
- }
- case 'q': {
- uint64_t *x;
-
- x = va_arg(vl, uint64_t *);
- rc = _fcall_read(fcall, x, sizeof(*x));
- if (rc < 0)
- goto out;
- break;
- }
- case 's': {
- struct uk_9p_str *p;
-
- p = va_arg(vl, struct uk_9p_str *);
- rc = _fcall_read(fcall, &p->size, sizeof(p->size));
- if (rc < 0)
- goto out;
- p->data = (char *)fcall->buf + fcall->offset;
- fcall->offset += p->size;
- break;
- }
- case 'Q': {
- struct uk_9p_qid *p;
-
- p = va_arg(vl, struct uk_9p_qid *);
- rc = _fcall_deserialize(fcall, "bdq", &p->type,
- &p->version, &p->path);
- if (rc < 0)
- goto out;
- break;
- }
- case 'S': {
- struct uk_9p_stat *p;
-
- p = va_arg(vl, struct uk_9p_stat *);
- rc = _fcall_deserialize(fcall, "wwdQdddqsssssddd",
- &p->size, &p->type, &p->dev, &p->qid,
- &p->mode, &p->atime, &p->mtime,
- &p->length, &p->name, &p->uid, &p->gid,
- &p->muid, &p->extension, &p->n_uid,
- &p->n_gid, &p->n_muid);
- if (rc < 0)
- goto out;
- break;
- }
- default:
- rc = -EINVAL;
- goto out;
- }
-
- fmt++;
- }
-
-out:
- return rc;
-}
-
-static int _fcall_deserialize(struct uk_9preq_fcall *f, const char *fmt, ...)
-{
- va_list vl;
- int rc;
-
- va_start(vl, fmt);
- rc = _fcall_vdeserialize(f, fmt, vl);
- va_end(vl);
-
- return rc;
-}
-
-int uk_9preq_vdeserialize(struct uk_9preq *req, const char *fmt, va_list vl)
-{
- int rc;
-
- UK_ASSERT(req);
- UK_ASSERT(UK_READ_ONCE(req->state) == UK_9PREQ_RECEIVED);
- rc = _fcall_vdeserialize(&req->recv, fmt, vl);
-
- return rc;
-}
-
-int uk_9preq_deserialize(struct uk_9preq *req, const char *fmt, ...)
-{
- va_list vl;
- int rc;
-
- va_start(vl, fmt);
- rc = uk_9preq_vdeserialize(req, fmt, vl);
- va_end(vl);
-
- return rc;
-}
-
-int uk_9preq_copy_to(struct uk_9preq *req, void *buf, uint32_t size)
-{
- return _fcall_read(&req->recv, buf, size);
-}
-
-int uk_9preq_copy_from(struct uk_9preq *req, const void *buf, uint32_t size)
-{
- return _fcall_write(&req->xmit, buf, size);
-}
-
int uk_9preq_ready(struct uk_9preq *req, enum uk_9preq_zcdir zc_dir,
void *zc_buf, uint32_t zc_size, uint32_t zc_offset)
{
@@ -434,10 +147,8 @@ int uk_9preq_ready(struct uk_9preq *req, enum
uk_9preq_zcdir zc_dir,
UK_ASSERT(req);
- if (UK_READ_ONCE(req->state) != UK_9PREQ_INITIALIZED) {
- rc = -EIO;
- goto out;
- }
+ if (UK_READ_ONCE(req->state) != UK_9PREQ_INITIALIZED)
+ return -EIO;
/* Save current offset as the size of the message. */
total_size = req->xmit.offset;
@@ -448,10 +159,10 @@ int uk_9preq_ready(struct uk_9preq *req, enum
uk_9preq_zcdir zc_dir,
/* Serialize the header. */
req->xmit.offset = 0;
- rc = uk_9preq_serialize(req, "dbw", total_size_with_zc, req->xmit.type,
- req->tag);
- if (rc < 0)
- goto out;
+ if ((rc = uk_9preq_write32(req, total_size_with_zc)) < 0 ||
+ (rc = uk_9preq_write8(req, req->xmit.type)) < 0 ||
+ (rc = uk_9preq_write16(req, req->tag)) < 0)
+ return rc;
/* Reset offset and size to sane values. */
req->xmit.offset = 0;
@@ -474,8 +185,7 @@ int uk_9preq_ready(struct uk_9preq *req, enum
uk_9preq_zcdir zc_dir,
/* Update the state. */
UK_WRITE_ONCE(req->state, UK_9PREQ_READY);
-out:
- return rc;
+ return 0;
}
int uk_9preq_receive_cb(struct uk_9preq *req, uint32_t recv_size)
@@ -495,8 +205,10 @@ int uk_9preq_receive_cb(struct uk_9preq *req, uint32_t
recv_size)
/* Deserialize the header into request fields. */
req->recv.offset = 0;
req->recv.size = recv_size;
- rc = _fcall_deserialize(&req->recv, "dbw", &size,
- &req->recv.type, &tag);
+ if ((rc = uk_9preq_read32(req, &size)) < 0 ||
+ (rc = uk_9preq_read8(req, &req->recv.type)) < 0 ||
+ (rc = uk_9preq_read16(req, &tag)) < 0)
+ return rc;
/* Check sanity of deserialized values. */
if (rc < 0)
@@ -557,8 +269,8 @@ int uk_9preq_error(struct uk_9preq *req)
*/
UK_BUGON(req->recv.offset != UK_9P_HEADER_SIZE);
- rc = uk_9preq_deserialize(req, "sd", &error, &errcode);
- if (rc < 0)
+ if ((rc = uk_9preq_readstr(req, &error)) < 0 ||
+ (rc = uk_9preq_read32(req, &errcode)) < 0)
return rc;
uk_pr_debug("RERROR %.*s %d\n", error.size, error.data, errcode);
diff --git a/lib/uk9p/exportsyms.uk b/lib/uk9p/exportsyms.uk
index aae9e8a..7f8e7dd 100644
--- a/lib/uk9p/exportsyms.uk
+++ b/lib/uk9p/exportsyms.uk
@@ -5,12 +5,6 @@ uk_9pdev_trans_set_default
uk_9preq_get
uk_9preq_put
-uk_9preq_vserialize
-uk_9preq_serialize
-uk_9preq_vdeserialize
-uk_9preq_deserialize
-uk_9preq_copy_to
-uk_9preq_copy_from
uk_9preq_receive_cb
uk_9preq_waitreply
uk_9preq_error
@@ -19,7 +13,6 @@ uk_9pdev_connect
uk_9pdev_disconnect
uk_9pdev_request
uk_9pdev_xmit_notify
-uk_9pdev_call
uk_9pdev_set_msize
uk_9pdev_get_msize
diff --git a/lib/uk9p/include/uk/9pdev.h b/lib/uk9p/include/uk/9pdev.h
index 139498f..04ff523 100644
--- a/lib/uk9p/include/uk/9pdev.h
+++ b/lib/uk9p/include/uk/9pdev.h
@@ -107,29 +107,6 @@ int uk_9pdev_request(struct uk_9pdev *dev, struct uk_9preq
*req);
*/
void uk_9pdev_xmit_notify(struct uk_9pdev *dev);
-/**
- * Creates and sends 9P request to the given 9P device, serializing it with
- * the given arguments. This function acts as a shorthand for the explicit
- * calls to req_create(), serialize(), ready(), request(), waitreply().
- *
- * @param dev
- * The Unikraft 9P Device.
- * @param type
- * Transmit type of the request, e.g. Tversion, Tread, and so on.
- * @param size
- * The maximum size for the receive and send buffers.
- * @param fmt
- * The format of the data to be serialized, in the way uk_9preq_serialize()
- * expects it.
- * @param ...
- * The arguments to be serialized.
- * @return
- * - (!PTRISERR): The 9p request in the UK_9PREQ_RECEIVED state.
- * - PTRISERR: The error code with which any of the steps failed.
- */
-struct uk_9preq *uk_9pdev_call(struct uk_9pdev *dev, uint8_t type,
- uint32_t size, const char *fmt, ...);
-
/**
* Create a new request, automatically allocating its tag, based on its type.
*
diff --git a/lib/uk9p/include/uk/9preq.h b/lib/uk9p/include/uk/9preq.h
index ee4d2af..b9713e2 100644
--- a/lib/uk9p/include/uk/9preq.h
+++ b/lib/uk9p/include/uk/9preq.h
@@ -41,6 +41,7 @@
#include <uk/essentials.h>
#include <uk/list.h>
#include <uk/refcount.h>
+#include <uk/9p_core.h>
#if CONFIG_LIBUKSCHED
#include <uk/wait_types.h>
#endif
@@ -181,61 +182,6 @@ void uk_9preq_get(struct uk_9preq *req);
*/
int uk_9preq_put(struct uk_9preq *req);
-/*
- * The following family of serialization and deserialization functions work
- * by employing a printf-like formatting mechanism for data types supported by
- * the 9p protocol:
- * - 'b': byte (uint8_t)
- * - 'w': word (uint16_t)
- * - 'd': double-word (uint32_t)
- * - 'q': quad-word (uint64_t)
- * - 's': uk_9p_str *
- * - 'S': uk_9p_stat *
- *
- * Similarly to vprintf(), the vserialize() and vdeserialize() functions take
- * a va_list instead of a variable number of arguments.
- *
- * Possible return values:
- * - 0: Operation successful.
- * - (-EINVAL): Invalid format specifier.
- * - (-ENOBUFS): End of buffer reached.
- */
-
-int uk_9preq_vserialize(struct uk_9preq *req, const char *fmt, va_list vl);
-int uk_9preq_serialize(struct uk_9preq *req, const char *fmt, ...);
-int uk_9preq_vdeserialize(struct uk_9preq *req, const char *fmt, va_list vl);
-int uk_9preq_deserialize(struct uk_9preq *req, const char *fmt, ...);
-
-/**
- * Copies raw data from the request receive buffer to the provided buffer.
- *
- * @param req
- * Reference to the 9p request.
- * @param buf
- * Destination buffer.
- * @param size
- * Amount to copy.
- * Possible return values:
- * - 0: Operation successful.
- * - (-ENOBUFS): End of buffer reached.
- */
-int uk_9preq_copy_to(struct uk_9preq *req, void *buf, uint32_t size);
-
-/**
- * Copies raw data from the provided buffer to the request transmission buffer.
- *
- * @param req
- * Reference to the 9p request.
- * @param buf
- * Source buffer.
- * @param size
- * Amount to copy.
- * Possible return values:
- * - 0: Operation successful.
- * - (-ENOBUFS): End of buffer reached.
- */
-int uk_9preq_copy_from(struct uk_9preq *req, const void *buf, uint32_t size);
-
/**
* Marks the given request as being ready, transitioning between states
* INITIALIZED and READY.
@@ -293,6 +239,189 @@ int uk_9preq_waitreply(struct uk_9preq *req);
*/
int uk_9preq_error(struct uk_9preq *req);
+/*
+ * The following family of serialization and deserialization functions
+ * are used for writing the 'base' types the 9p protocol supports.
+ *
+ * These are defined in the header for better performance by not necessarily
+ * incurring a function call penalty if called from outside uk9p.
+ *
+ * Provided functions:
+ * - uk_9preq_{read,write}buf
+ * - uk_9preq_{read,write}8
+ * - uk_9preq_{read,write}16
+ * - uk_9preq_{read,write}32
+ * - uk_9preq_{read,write}64
+ * - uk_9preq_{read,write}qid
+ * - uk_9preq_{read,write}str
+ * - uk_9preq_{read,write}stat
+ *
+ * For qid, str and stat, read and write always take a pointer.
+ * For all other types, write takes the argument by value.
+ *
+ * Possible return values:
+ * - 0: Operation successful.
+ * - (-ENOBUFS): End of buffer reached.
+ */
+
+static inline int uk_9preq_writebuf(struct uk_9preq *req, const void *buf,
+ uint32_t size)
+{
+ if (req->xmit.offset + size > req->xmit.size)
+ return -ENOBUFS;
+
+ memcpy((char *)req->xmit.buf + req->xmit.offset, buf, size);
+ req->xmit.offset += size;
+ return 0;
+}
+
+static inline int uk_9preq_readbuf(struct uk_9preq *req, void *buf,
+ uint32_t size)
+{
+ if (req->recv.offset + size > req->recv.size)
+ return -ENOBUFS;
+
+ memcpy(buf, (char *)req->recv.buf + req->recv.offset, size);
+ req->recv.offset += size;
+ return 0;
+}
+
+#define _UK_9PREQ_DEFINE_WRITE_FN(name, ctype) \
+static inline int uk_9preq_##name(struct uk_9preq *req, ctype val) \
+{ \
+ return uk_9preq_writebuf(req, &val, sizeof(val)); \
+}
+
+_UK_9PREQ_DEFINE_WRITE_FN(write8, uint8_t)
+_UK_9PREQ_DEFINE_WRITE_FN(write16, uint16_t)
+_UK_9PREQ_DEFINE_WRITE_FN(write32, uint32_t)
+_UK_9PREQ_DEFINE_WRITE_FN(write64, uint64_t)
+
+#undef _UK_9PREQ_DEFINE_WRITE_FN
+
+static inline int uk_9preq_writeqid(struct uk_9preq *req, struct uk_9p_qid
*val)
+{
+ int rc;
+
+ if ((rc = uk_9preq_write8(req, val->type)) ||
+ (rc = uk_9preq_write32(req, val->version)) ||
+ (rc = uk_9preq_write64(req, val->path)))
+ return rc;
+
+ return 0;
+}
+
+static inline int uk_9preq_writestr(struct uk_9preq *req, struct uk_9p_str
*val)
+{
+ int rc;
+
+ if ((rc = uk_9preq_write16(req, val->size)) ||
+ (rc = uk_9preq_writebuf(req, val->data, val->size)))
+ return rc;
+
+ return 0;
+}
+
+static inline int uk_9preq_writestat(struct uk_9preq *req,
+ struct uk_9p_stat *val)
+{
+ int rc;
+
+ val->size = 61;
+ val->size += val->name.size;
+ val->size += val->uid.size;
+ val->size += val->gid.size;
+ val->size += val->muid.size;
+ val->size += val->extension.size;
+
+ if ((rc = uk_9preq_write16(req, val->size)) ||
+ (rc = uk_9preq_write16(req, val->type)) ||
+ (rc = uk_9preq_write32(req, val->dev)) ||
+ (rc = uk_9preq_writeqid(req, &val->qid)) ||
+ (rc = uk_9preq_write32(req, val->mode)) ||
+ (rc = uk_9preq_write32(req, val->atime)) ||
+ (rc = uk_9preq_write32(req, val->mtime)) ||
+ (rc = uk_9preq_write64(req, val->length)) ||
+ (rc = uk_9preq_writestr(req, &val->name)) ||
+ (rc = uk_9preq_writestr(req, &val->uid)) ||
+ (rc = uk_9preq_writestr(req, &val->gid)) ||
+ (rc = uk_9preq_writestr(req, &val->muid)) ||
+ (rc = uk_9preq_writestr(req, &val->extension)) ||
+ (rc = uk_9preq_write32(req, val->n_uid)) ||
+ (rc = uk_9preq_write32(req, val->n_gid)) ||
+ (rc = uk_9preq_write32(req, val->n_muid)))
+ return rc;
+
+ return 0;
+}
+
+#define _UK_9PREQ_DEFINE_READ_FN(name, ctype) \
+static inline int uk_9preq_##name(struct uk_9preq *req, ctype * val) \
+{ \
+ return uk_9preq_readbuf(req, val, sizeof(*val)); \
+}
+
+_UK_9PREQ_DEFINE_READ_FN(read8, uint8_t)
+_UK_9PREQ_DEFINE_READ_FN(read16, uint16_t)
+_UK_9PREQ_DEFINE_READ_FN(read32, uint32_t)
+_UK_9PREQ_DEFINE_READ_FN(read64, uint64_t)
+
+#undef _UK_9PREQ_DEFINE_READ_FN
+
+static inline int uk_9preq_readqid(struct uk_9preq *req, struct uk_9p_qid *val)
+{
+ int rc;
+
+ if ((rc = uk_9preq_read8(req, &val->type)) ||
+ (rc = uk_9preq_read32(req, &val->version)) ||
+ (rc = uk_9preq_read64(req, &val->path)))
+ return rc;
+
+ return 0;
+}
+
+static inline int uk_9preq_readstr(struct uk_9preq *req, struct uk_9p_str *val)
+{
+ int rc;
+
+ if ((rc = uk_9preq_read16(req, &val->size)))
+ return rc;
+
+ /* Optimized string read, does not allocate memory. */
+ val->data = (char *)req->recv.buf + req->recv.offset;
+ req->recv.offset += val->size;
+ if (req->recv.offset > req->recv.size)
+ return -ENOBUFS;
+
+ return 0;
+}
+
+static inline int uk_9preq_readstat(struct uk_9preq *req,
+ struct uk_9p_stat *val)
+{
+ int rc;
+
+ if ((rc = uk_9preq_read16(req, &val->size)) ||
+ (rc = uk_9preq_read16(req, &val->type)) ||
+ (rc = uk_9preq_read32(req, &val->dev)) ||
+ (rc = uk_9preq_readqid(req, &val->qid)) ||
+ (rc = uk_9preq_read32(req, &val->mode)) ||
+ (rc = uk_9preq_read32(req, &val->atime)) ||
+ (rc = uk_9preq_read32(req, &val->mtime)) ||
+ (rc = uk_9preq_read64(req, &val->length)) ||
+ (rc = uk_9preq_readstr(req, &val->name)) ||
+ (rc = uk_9preq_readstr(req, &val->uid)) ||
+ (rc = uk_9preq_readstr(req, &val->gid)) ||
+ (rc = uk_9preq_readstr(req, &val->muid)) ||
+ (rc = uk_9preq_readstr(req, &val->extension)) ||
+ (rc = uk_9preq_read32(req, &val->n_uid)) ||
+ (rc = uk_9preq_read32(req, &val->n_gid)) ||
+ (rc = uk_9preq_read32(req, &val->n_muid)))
+ return rc;
+
+ return 0;
+}
+
#ifdef __cplusplus
}
#endif
--
2.26.2
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |