#include "hw/hw.h"
#include "hw/9pfs/9p.h"
-#include "hw/xen/xen_backend.h"
+#include "hw/xen/xen-legacy-backend.h"
#include "hw/9pfs/xen-9pfs.h"
+#include "qapi/error.h"
#include "qemu/config-file.h"
+#include "qemu/option.h"
#include "fsdev/qemu-fsdev.h"
#define VERSIONS "1"
} Xen9pfsRing;
typedef struct Xen9pfsDev {
- struct XenDevice xendev; /* must be first */
+ struct XenLegacyDevice xendev; /* must be first */
V9fsState state;
char *path;
char *security_model;
Xen9pfsRing *rings;
} Xen9pfsDev;
+static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev);
+
static void xen_9pfs_in_sg(Xen9pfsRing *ring,
struct iovec *in_sg,
int *num,
Xen9pfsDev *xen_9pfs = container_of(pdu->s, Xen9pfsDev, state);
struct iovec in_sg[2];
int num;
+ ssize_t ret;
xen_9pfs_in_sg(&xen_9pfs->rings[pdu->tag % xen_9pfs->num_rings],
in_sg, &num, pdu->idx, ROUND_UP(offset + 128, 512));
- return v9fs_iov_vmarshal(in_sg, num, offset, 0, fmt, ap);
+
+ ret = v9fs_iov_vmarshal(in_sg, num, offset, 0, fmt, ap);
+ if (ret < 0) {
+ xen_pv_printf(&xen_9pfs->xendev, 0,
+ "Failed to encode VirtFS request type %d\n", pdu->id + 1);
+ xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing);
+ xen_9pfs_disconnect(&xen_9pfs->xendev);
+ }
+ return ret;
}
static ssize_t xen_9pfs_pdu_vunmarshal(V9fsPDU *pdu,
Xen9pfsDev *xen_9pfs = container_of(pdu->s, Xen9pfsDev, state);
struct iovec out_sg[2];
int num;
+ ssize_t ret;
xen_9pfs_out_sg(&xen_9pfs->rings[pdu->tag % xen_9pfs->num_rings],
out_sg, &num, pdu->idx);
- return v9fs_iov_vunmarshal(out_sg, num, offset, 0, fmt, ap);
+
+ ret = v9fs_iov_vunmarshal(out_sg, num, offset, 0, fmt, ap);
+ if (ret < 0) {
+ xen_pv_printf(&xen_9pfs->xendev, 0,
+ "Failed to decode VirtFS request type %d\n", pdu->id);
+ xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing);
+ xen_9pfs_disconnect(&xen_9pfs->xendev);
+ }
+ return ret;
}
static void xen_9pfs_init_out_iov_from_pdu(V9fsPDU *pdu,
g_free(ring->sg);
- ring->sg = g_malloc0(sizeof(*ring->sg) * 2);
+ ring->sg = g_new0(struct iovec, 2);
xen_9pfs_out_sg(ring, ring->sg, &num, pdu->idx);
*piov = ring->sg;
*pniov = num;
Xen9pfsDev *xen_9pfs = container_of(pdu->s, Xen9pfsDev, state);
Xen9pfsRing *ring = &xen_9pfs->rings[pdu->tag % xen_9pfs->num_rings];
int num;
+ size_t buf_size;
g_free(ring->sg);
- ring->sg = g_malloc0(sizeof(*ring->sg) * 2);
+ ring->sg = g_new0(struct iovec, 2);
xen_9pfs_in_sg(ring, ring->sg, &num, pdu->idx, size);
+
+ buf_size = iov_size(ring->sg, num);
+ if (buf_size < size) {
+ xen_pv_printf(&xen_9pfs->xendev, 0, "Xen 9pfs request type %d"
+ "needs %zu bytes, buffer has %zu\n", pdu->id, size,
+ buf_size);
+ xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing);
+ xen_9pfs_disconnect(&xen_9pfs->xendev);
+ }
+
*piov = ring->sg;
*pniov = num;
}
qemu_bh_schedule(ring->bh);
}
-static const struct V9fsTransport xen_9p_transport = {
+static const V9fsTransport xen_9p_transport = {
.pdu_vmarshal = xen_9pfs_pdu_vmarshal,
.pdu_vunmarshal = xen_9pfs_pdu_vunmarshal,
.init_in_iov_from_pdu = xen_9pfs_init_in_iov_from_pdu,
.push_and_notify = xen_9pfs_push_and_notify,
};
-static int xen_9pfs_init(struct XenDevice *xendev)
+static int xen_9pfs_init(struct XenLegacyDevice *xendev)
{
return 0;
}
static int xen_9pfs_receive(Xen9pfsRing *ring)
{
P9MsgHeader h;
- RING_IDX cons, prod, masked_prod, masked_cons;
+ RING_IDX cons, prod, masked_prod, masked_cons, queued;
V9fsPDU *pdu;
if (ring->inprogress) {
prod = ring->intf->out_prod;
xen_rmb();
- if (xen_9pfs_queued(prod, cons, XEN_FLEX_RING_SIZE(ring->ring_order)) <
- sizeof(h)) {
+ queued = xen_9pfs_queued(prod, cons, XEN_FLEX_RING_SIZE(ring->ring_order));
+ if (queued < sizeof(h)) {
return 0;
}
ring->inprogress = true;
xen_9pfs_read_packet((uint8_t *) &h, ring->ring.out, sizeof(h),
masked_prod, &masked_cons,
XEN_FLEX_RING_SIZE(ring->ring_order));
+ if (queued < le32_to_cpu(h.size_le)) {
+ return 0;
+ }
/* cannot fail, because we only handle one request per ring at a time */
pdu = pdu_alloc(&ring->priv->state);
qemu_bh_schedule(ring->bh);
}
-static int xen_9pfs_free(struct XenDevice *xendev)
+static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev)
{
+ Xen9pfsDev *xen_9pdev = container_of(xendev, Xen9pfsDev, xendev);
int i;
+
+ for (i = 0; i < xen_9pdev->num_rings; i++) {
+ if (xen_9pdev->rings[i].evtchndev != NULL) {
+ qemu_set_fd_handler(xenevtchn_fd(xen_9pdev->rings[i].evtchndev),
+ NULL, NULL, NULL);
+ xenevtchn_unbind(xen_9pdev->rings[i].evtchndev,
+ xen_9pdev->rings[i].local_port);
+ xen_9pdev->rings[i].evtchndev = NULL;
+ }
+ }
+}
+
+static int xen_9pfs_free(struct XenLegacyDevice *xendev)
+{
Xen9pfsDev *xen_9pdev = container_of(xendev, Xen9pfsDev, xendev);
+ int i;
- g_free(xen_9pdev->id);
- g_free(xen_9pdev->tag);
- g_free(xen_9pdev->path);
- g_free(xen_9pdev->security_model);
+ if (xen_9pdev->rings[0].evtchndev != NULL) {
+ xen_9pfs_disconnect(xendev);
+ }
for (i = 0; i < xen_9pdev->num_rings; i++) {
if (xen_9pdev->rings[i].data != NULL) {
- xengnttab_unmap(xen_9pdev->xendev.gnttabdev,
- xen_9pdev->rings[i].data,
- (1 << xen_9pdev->rings[i].ring_order));
+ xen_be_unmap_grant_refs(&xen_9pdev->xendev,
+ xen_9pdev->rings[i].data,
+ (1 << xen_9pdev->rings[i].ring_order));
}
if (xen_9pdev->rings[i].intf != NULL) {
- xengnttab_unmap(xen_9pdev->xendev.gnttabdev,
- xen_9pdev->rings[i].intf,
- 1);
- }
- if (xen_9pdev->rings[i].evtchndev > 0) {
- qemu_set_fd_handler(xenevtchn_fd(xen_9pdev->rings[i].evtchndev),
- NULL, NULL, NULL);
- xenevtchn_unbind(xen_9pdev->rings[i].evtchndev,
- xen_9pdev->rings[i].local_port);
+ xen_be_unmap_grant_refs(&xen_9pdev->xendev,
+ xen_9pdev->rings[i].intf,
+ 1);
}
if (xen_9pdev->rings[i].bh != NULL) {
qemu_bh_delete(xen_9pdev->rings[i].bh);
}
}
+
+ g_free(xen_9pdev->id);
+ g_free(xen_9pdev->tag);
+ g_free(xen_9pdev->path);
+ g_free(xen_9pdev->security_model);
g_free(xen_9pdev->rings);
return 0;
}
-static int xen_9pfs_connect(struct XenDevice *xendev)
+static int xen_9pfs_connect(struct XenLegacyDevice *xendev)
{
+ Error *err = NULL;
int i;
Xen9pfsDev *xen_9pdev = container_of(xendev, Xen9pfsDev, xendev);
V9fsState *s = &xen_9pdev->state;
return -1;
}
- xen_9pdev->rings = g_malloc0(xen_9pdev->num_rings * sizeof(Xen9pfsRing));
+ xen_9pdev->rings = g_new0(Xen9pfsRing, xen_9pdev->num_rings);
for (i = 0; i < xen_9pdev->num_rings; i++) {
char *str;
int ring_order;
}
g_free(str);
- xen_9pdev->rings[i].intf = xengnttab_map_grant_ref(
- xen_9pdev->xendev.gnttabdev,
- xen_9pdev->xendev.dom,
- xen_9pdev->rings[i].ref,
- PROT_READ | PROT_WRITE);
+ xen_9pdev->rings[i].intf =
+ xen_be_map_grant_ref(&xen_9pdev->xendev,
+ xen_9pdev->rings[i].ref,
+ PROT_READ | PROT_WRITE);
if (!xen_9pdev->rings[i].intf) {
goto out;
}
goto out;
}
xen_9pdev->rings[i].ring_order = ring_order;
- xen_9pdev->rings[i].data = xengnttab_map_domain_grant_refs(
- xen_9pdev->xendev.gnttabdev,
- (1 << ring_order),
- xen_9pdev->xendev.dom,
- xen_9pdev->rings[i].intf->ref,
- PROT_READ | PROT_WRITE);
+ xen_9pdev->rings[i].data =
+ xen_be_map_grant_refs(&xen_9pdev->xendev,
+ xen_9pdev->rings[i].intf->ref,
+ (1 << ring_order),
+ PROT_READ | PROT_WRITE);
if (!xen_9pdev->rings[i].data) {
goto out;
}
xen_9pdev->id = s->fsconf.fsdev_id =
g_strdup_printf("xen9p%d", xendev->dev);
xen_9pdev->tag = s->fsconf.tag = xenstore_read_fe_str(xendev, "tag");
- v9fs_register_transport(s, &xen_9p_transport);
fsdev = qemu_opts_create(qemu_find_opts("fsdev"),
s->fsconf.tag,
1, NULL);
qemu_opt_set(fsdev, "path", xen_9pdev->path, NULL);
qemu_opt_set(fsdev, "security_model", xen_9pdev->security_model, NULL);
qemu_opts_set_id(fsdev, s->fsconf.fsdev_id);
- qemu_fsdev_add(fsdev);
- v9fs_device_realize_common(s, NULL);
+ qemu_fsdev_add(fsdev, &err);
+ if (err) {
+ error_report_err(err);
+ }
+ v9fs_device_realize_common(s, &xen_9p_transport, NULL);
return 0;
return -1;
}
-static void xen_9pfs_alloc(struct XenDevice *xendev)
+static void xen_9pfs_alloc(struct XenLegacyDevice *xendev)
{
xenstore_write_be_str(xendev, "versions", VERSIONS);
xenstore_write_be_int(xendev, "max-rings", MAX_RINGS);
xenstore_write_be_int(xendev, "max-ring-page-order", MAX_RING_ORDER);
}
-static void xen_9pfs_disconnect(struct XenDevice *xendev)
-{
- /* Dynamic hotplug of PV filesystems at runtime is not supported. */
-}
-
struct XenDevOps xen_9pfs_ops = {
.size = sizeof(Xen9pfsDev),
.flags = DEVOPS_FLAG_NEED_GNTDEV,