summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/9pfs/virtio-9p-local.c49
-rw-r--r--hw/net/virtio-net.c15
-rw-r--r--hw/virtio/virtio.c9
-rw-r--r--net/net.c40
-rw-r--r--net/queue.c3
5 files changed, 88 insertions, 28 deletions
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 3b0b6a9b1d..a183eee662 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -135,17 +135,17 @@ static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
mode_t tmp_mode;
dev_t tmp_dev;
if (getxattr(buffer, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) {
- stbuf->st_uid = tmp_uid;
+ stbuf->st_uid = le32_to_cpu(tmp_uid);
}
if (getxattr(buffer, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) {
- stbuf->st_gid = tmp_gid;
+ stbuf->st_gid = le32_to_cpu(tmp_gid);
}
if (getxattr(buffer, "user.virtfs.mode",
&tmp_mode, sizeof(mode_t)) > 0) {
- stbuf->st_mode = tmp_mode;
+ stbuf->st_mode = le32_to_cpu(tmp_mode);
}
if (getxattr(buffer, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) {
- stbuf->st_rdev = tmp_dev;
+ stbuf->st_rdev = le64_to_cpu(tmp_dev);
}
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
local_mapped_file_attr(fs_ctx, path, stbuf);
@@ -255,29 +255,29 @@ static int local_set_xattr(const char *path, FsCred *credp)
int err;
if (credp->fc_uid != -1) {
- err = setxattr(path, "user.virtfs.uid", &credp->fc_uid, sizeof(uid_t),
- 0);
+ uint32_t tmp_uid = cpu_to_le32(credp->fc_uid);
+ err = setxattr(path, "user.virtfs.uid", &tmp_uid, sizeof(uid_t), 0);
if (err) {
return err;
}
}
if (credp->fc_gid != -1) {
- err = setxattr(path, "user.virtfs.gid", &credp->fc_gid, sizeof(gid_t),
- 0);
+ uint32_t tmp_gid = cpu_to_le32(credp->fc_gid);
+ err = setxattr(path, "user.virtfs.gid", &tmp_gid, sizeof(gid_t), 0);
if (err) {
return err;
}
}
if (credp->fc_mode != -1) {
- err = setxattr(path, "user.virtfs.mode", &credp->fc_mode,
- sizeof(mode_t), 0);
+ uint32_t tmp_mode = cpu_to_le32(credp->fc_mode);
+ err = setxattr(path, "user.virtfs.mode", &tmp_mode, sizeof(mode_t), 0);
if (err) {
return err;
}
}
if (credp->fc_rdev != -1) {
- err = setxattr(path, "user.virtfs.rdev", &credp->fc_rdev,
- sizeof(dev_t), 0);
+ uint64_t tmp_rdev = cpu_to_le64(credp->fc_rdev);
+ err = setxattr(path, "user.virtfs.rdev", &tmp_rdev, sizeof(dev_t), 0);
if (err) {
return err;
}
@@ -397,12 +397,15 @@ static int local_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
again:
ret = readdir_r(fs->dir, entry, result);
- if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+ if (ctx->export_flags & V9FS_SM_MAPPED) {
+ entry->d_type = DT_UNKNOWN;
+ } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
if (!ret && *result != NULL &&
!strcmp(entry->d_name, VIRTFS_META_DIR)) {
/* skp the meta data directory */
goto again;
}
+ entry->d_type = DT_UNKNOWN;
}
return ret;
}
@@ -630,21 +633,17 @@ static int local_fstat(FsContext *fs_ctx, int fid_type,
mode_t tmp_mode;
dev_t tmp_dev;
- if (fgetxattr(fd, "user.virtfs.uid",
- &tmp_uid, sizeof(uid_t)) > 0) {
- stbuf->st_uid = tmp_uid;
+ if (fgetxattr(fd, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) {
+ stbuf->st_uid = le32_to_cpu(tmp_uid);
}
- if (fgetxattr(fd, "user.virtfs.gid",
- &tmp_gid, sizeof(gid_t)) > 0) {
- stbuf->st_gid = tmp_gid;
+ if (fgetxattr(fd, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) {
+ stbuf->st_gid = le32_to_cpu(tmp_gid);
}
- if (fgetxattr(fd, "user.virtfs.mode",
- &tmp_mode, sizeof(mode_t)) > 0) {
- stbuf->st_mode = tmp_mode;
+ if (fgetxattr(fd, "user.virtfs.mode", &tmp_mode, sizeof(mode_t)) > 0) {
+ stbuf->st_mode = le32_to_cpu(tmp_mode);
}
- if (fgetxattr(fd, "user.virtfs.rdev",
- &tmp_dev, sizeof(dev_t)) > 0) {
- stbuf->st_rdev = tmp_dev;
+ if (fgetxattr(fd, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) {
+ stbuf->st_rdev = le64_to_cpu(tmp_dev);
}
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
errno = EOPNOTSUPP;
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 365e266b74..826a2a5fca 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -125,10 +125,23 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
return;
}
if (!n->vhost_started) {
- int r;
+ int r, i;
+
if (!vhost_net_query(get_vhost_net(nc->peer), vdev)) {
return;
}
+
+ /* Any packets outstanding? Purge them to avoid touching rings
+ * when vhost is running.
+ */
+ for (i = 0; i < queues; i++) {
+ NetClientState *qnc = qemu_get_subqueue(n->nic, i);
+
+ /* Purge both directions: TX and RX. */
+ qemu_net_queue_purge(qnc->peer->incoming_queue, qnc);
+ qemu_net_queue_purge(qnc->incoming_queue, qnc->peer);
+ }
+
n->vhost_started = 1;
r = vhost_net_start(vdev, n->nic->ncs, queues);
if (r < 0) {
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 5c981801f3..ac222385d6 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1108,7 +1108,10 @@ static void virtio_vmstate_change(void *opaque, int running, RunState state)
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
bool backend_run = running && (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK);
- vdev->vm_running = running;
+
+ if (running) {
+ vdev->vm_running = running;
+ }
if (backend_run) {
virtio_set_status(vdev, vdev->status);
@@ -1121,6 +1124,10 @@ static void virtio_vmstate_change(void *opaque, int running, RunState state)
if (!backend_run) {
virtio_set_status(vdev, vdev->status);
}
+
+ if (!running) {
+ vdev->vm_running = running;
+ }
}
void virtio_init(VirtIODevice *vdev, const char *name,
diff --git a/net/net.c b/net/net.c
index 6d930ea63b..7acc162b44 100644
--- a/net/net.c
+++ b/net/net.c
@@ -41,12 +41,14 @@
#include "qapi-visit.h"
#include "qapi/opts-visitor.h"
#include "qapi/dealloc-visitor.h"
+#include "sysemu/sysemu.h"
/* Net bridge is currently not supported for W32. */
#if !defined(_WIN32)
# define CONFIG_NET_BRIDGE
#endif
+static VMChangeStateEntry *net_change_state_entry;
static QTAILQ_HEAD(, NetClientState) net_clients;
const char *host_net_devices[] = {
@@ -452,6 +454,12 @@ void qemu_set_vnet_hdr_len(NetClientState *nc, int len)
int qemu_can_send_packet(NetClientState *sender)
{
+ int vm_running = runstate_is_running();
+
+ if (!vm_running) {
+ return 0;
+ }
+
if (!sender->peer) {
return 1;
}
@@ -504,7 +512,8 @@ void qemu_purge_queued_packets(NetClientState *nc)
qemu_net_queue_purge(nc->peer->incoming_queue, nc);
}
-void qemu_flush_queued_packets(NetClientState *nc)
+static
+void qemu_flush_or_purge_queued_packets(NetClientState *nc, bool purge)
{
nc->receive_disabled = 0;
@@ -518,9 +527,17 @@ void qemu_flush_queued_packets(NetClientState *nc)
* the file descriptor (for tap, for example).
*/
qemu_notify_event();
+ } else if (purge) {
+ /* Unable to empty the queue, purge remaining packets */
+ qemu_net_queue_purge(nc->incoming_queue, nc);
}
}
+void qemu_flush_queued_packets(NetClientState *nc)
+{
+ qemu_flush_or_purge_queued_packets(nc, false);
+}
+
static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
unsigned flags,
const uint8_t *buf, int size,
@@ -1168,6 +1185,22 @@ void qmp_set_link(const char *name, bool up, Error **errp)
}
}
+static void net_vm_change_state_handler(void *opaque, int running,
+ RunState state)
+{
+ /* Complete all queued packets, to guarantee we don't modify
+ * state later when VM is not running.
+ */
+ if (!running) {
+ NetClientState *nc;
+ NetClientState *tmp;
+
+ QTAILQ_FOREACH_SAFE(nc, &net_clients, next, tmp) {
+ qemu_flush_or_purge_queued_packets(nc, true);
+ }
+ }
+}
+
void net_cleanup(void)
{
NetClientState *nc;
@@ -1183,6 +1216,8 @@ void net_cleanup(void)
qemu_del_net_client(nc);
}
}
+
+ qemu_del_vm_change_state_handler(net_change_state_entry);
}
void net_check_clients(void)
@@ -1268,6 +1303,9 @@ int net_init_clients(void)
#endif
}
+ net_change_state_entry =
+ qemu_add_vm_change_state_handler(net_vm_change_state_handler, NULL);
+
QTAILQ_INIT(&net_clients);
if (qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL, 1) == -1)
diff --git a/net/queue.c b/net/queue.c
index 859d02a136..f948318718 100644
--- a/net/queue.c
+++ b/net/queue.c
@@ -233,6 +233,9 @@ void qemu_net_queue_purge(NetQueue *queue, NetClientState *from)
if (packet->sender == from) {
QTAILQ_REMOVE(&queue->packets, packet, entry);
queue->nq_count--;
+ if (packet->sent_cb) {
+ packet->sent_cb(packet->sender, 0);
+ }
g_free(packet);
}
}