[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 |