[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[UNIKRAFT PATCH v2 2/9] lib/uk9p: Switch to using the new serialization



This patch migrates 9p.c and 9pfs to use the new serialization
implementation.

Signed-off-by: Cristian Banu <cristb@xxxxxxxxx>
---
 lib/9pfs/9pfs_vnops.c |   2 +-
 lib/uk9p/9p.c         | 302 +++++++++++++++++++++++++-----------------
 lib/uk9p/9preq.c      |  27 ++--
 3 files changed, 192 insertions(+), 139 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/9preq.c b/lib/uk9p/9preq.c
index 0fc4b1e..8d787e7 100644
--- a/lib/uk9p/9preq.c
+++ b/lib/uk9p/9preq.c
@@ -434,10 +434,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 +446,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 +472,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 +492,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 +556,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);
-- 
2.26.2




 


Rackspace

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