If caching of buffers upon closing a port is not desired, delete all the buffers queued up for the port upon port close. This only applies to generic ports; console ports aren't opened / closed by the chardev interface. Signed-off-by: Amit Shah <amit.shah@xxxxxxxxxx> --- drivers/char/virtio_console.c | 49 +++++++++++++++++++++++++++++++++++---- include/linux/virtio_console.h | 2 + 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index c45b987..90bb221 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -169,6 +169,9 @@ struct virtio_console_port { /* Have we sent out a throttle request to the Host? */ bool guest_throttled; + + /* Does the port want to cache data when disconnected? */ + bool cache_buffers; }; struct virtio_console_struct virtconsole; @@ -501,6 +504,21 @@ static int virtconsole_release(struct inode *inode, struct file *filp) spin_lock(&port->readbuf_list_lock); port->guest_connected = false; + + /* + * If the port doesn't want to cache buffers while closed, + * flush the unread buffers queue + */ + if (!port->cache_buffers) { + struct virtio_console_port_buffer *buf, *buf2; + + list_for_each_entry_safe(buf, buf2, &port->readbuf_head, list) { + list_del(&buf->list); + kfree(buf->buf); + kfree(buf); + port->nr_buffers--; + } + } spin_unlock(&port->readbuf_list_lock); return 0; @@ -778,6 +796,9 @@ static void handle_control_message(struct virtio_console_port *port, */ port->buffer_limit = (u32)cpkt->value * 1024 / 4; break; + case VIRTIO_CONSOLE_CACHE_BUFFERS: + port->cache_buffers = cpkt->value; + break; } } @@ -907,7 +928,20 @@ static void virtio_console_rx_work_handler(struct work_struct *work) * initialised. */ port->host_connected = true; - + /* + * Don't queue up buffers if caching is + * disabled and port is closed. This condition + * can be reached when a console port is not + * yet connected (no tty is spawned) and the + * host sends out data to console ports. For + * generic serial ports, the host won't send + * data till the guest is connected. + */ + if (!port->guest_connected && !port->cache_buffers) { + kfree(buf->buf); + kfree(buf); + continue; + } if (port->guest_throttled) { kfree(buf->buf); kfree(buf); @@ -1058,6 +1092,8 @@ static ssize_t virtcon_port_debugfs_read(struct file *filp, char __user *ubuf, out_offset += snprintf(buf + out_offset, out_count - out_offset, "nr_buffers: %u\n", port->nr_buffers); out_offset += snprintf(buf + out_offset, out_count - out_offset, + "cache_buffers: %d\n", port->cache_buffers); + out_offset += snprintf(buf + out_offset, out_count - out_offset, "host_connected: %d\n", port->host_connected); out_offset += snprintf(buf + out_offset, out_count - out_offset, "host_throttled: %d\n", port->host_throttled); @@ -1232,17 +1268,19 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) { multiport = true; vdev->features[0] |= 1 << VIRTIO_CONSOLE_F_MULTIPORT; - vdev->config->finalize_features(vdev); vdev->config->get(vdev, offsetof(struct virtio_console_config, nr_ports), &virtconsole.config.nr_ports, sizeof(virtconsole.config.nr_ports)); } - if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_THROTTLE)) { + if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_THROTTLE)) vdev->features[0] |= 1 << VIRTIO_CONSOLE_F_THROTTLE; - vdev->config->finalize_features(vdev); - } + + if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_CACHING)) + vdev->features[0] |= 1 << VIRTIO_CONSOLE_F_CACHING; + + vdev->config->finalize_features(vdev); /* Find the queues. */ /* FIXME: This is why we want to wean off hvc: we do nothing * when input comes in. */ @@ -1294,6 +1332,7 @@ static unsigned int features[] = { VIRTIO_CONSOLE_F_SIZE, VIRTIO_CONSOLE_F_MULTIPORT, VIRTIO_CONSOLE_F_THROTTLE, + VIRTIO_CONSOLE_F_CACHING, }; static struct virtio_driver virtio_console = { diff --git a/include/linux/virtio_console.h b/include/linux/virtio_console.h index 5336a75..ce5eef2 100644 --- a/include/linux/virtio_console.h +++ b/include/linux/virtio_console.h @@ -14,6 +14,7 @@ #define VIRTIO_CONSOLE_F_SIZE 0 /* Does host provide console size? */ #define VIRTIO_CONSOLE_F_MULTIPORT 1 /* Does host provide multiple ports? */ #define VIRTIO_CONSOLE_F_THROTTLE 2 /* Do we throttle data to prevent OOM */ +#define VIRTIO_CONSOLE_F_CACHING 3 /* Do we cache data after port close? */ struct virtio_console_config { /* colums of the screens */ @@ -40,6 +41,7 @@ struct virtio_console_control { #define VIRTIO_CONSOLE_RESIZE 3 #define VIRTIO_CONSOLE_THROTTLE_PORT 4 #define VIRTIO_CONSOLE_BUFFER_LIMIT 5 +#define VIRTIO_CONSOLE_CACHE_BUFFERS 6 /* * This struct is put in each buffer that gets passed to userspace and -- 1.6.2.5 _______________________________________________ Virtualization mailing list Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/virtualization