[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




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.