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 | 37 ++++++++++++++++++++++++++++++++++++- include/linux/virtio_console.h | 1 + 2 files changed, 37 insertions(+), 1 deletions(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index fe8f14f..8fac9eb 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -195,6 +195,9 @@ struct 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; }; /* This is the very early arch-specified put chars function. */ @@ -506,8 +509,25 @@ static int port_fops_release(struct inode *inode, struct file *filp) /* Notify host of port being closed */ send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0); + spin_lock_irq(&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 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_irq(&port->readbuf_list_lock); + return 0; } @@ -869,6 +889,9 @@ static void handle_control_message(struct port *port, struct port_buffer *buf) */ port->buffer_limit = (u32)cpkt->value * 1024 / 4; break; + case VIRTIO_CONSOLE_CACHE_BUFFERS: + port->cache_buffers = cpkt->value; + break; } } @@ -938,7 +961,19 @@ static void rx_work_handler(struct work_struct *work) * e.g. before the queues were 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); diff --git a/include/linux/virtio_console.h b/include/linux/virtio_console.h index 2aa2b42..70924a1 100644 --- a/include/linux/virtio_console.h +++ b/include/linux/virtio_console.h @@ -40,6 +40,7 @@ struct virtio_console_control { #define VIRTIO_CONSOLE_PORT_NAME 4 #define VIRTIO_CONSOLE_THROTTLE_PORT 5 #define VIRTIO_CONSOLE_BUFFER_LIMIT 6 +#define VIRTIO_CONSOLE_CACHE_BUFFERS 7 /* * This struct is put at the start of each buffer that gets passed to -- 1.6.2.5 _______________________________________________ Virtualization mailing list Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/virtualization