Skip to content

Commit

Permalink
virtio/console: Allocate scatterlist according to the current pipe size
Browse files Browse the repository at this point in the history
Allocate scatterlist according to the current pipe size.
This allows splicing bigger buffer if the pipe size has
been changed by fcntl.

Changes in v2:
 - Just a minor fix for avoiding a confliction with previous patch.

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Acked-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
  • Loading branch information
Masami Hiramatsu authored and Rusty Russell committed Sep 28, 2012
1 parent d55cb6c commit 8ca84a5
Showing 1 changed file with 12 additions and 11 deletions.
23 changes: 12 additions & 11 deletions drivers/char/virtio_console.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,6 @@ struct port {
bool guest_connected;
};

#define MAX_SPLICE_PAGES 32
/* This is the very early arch-specified put chars function. */
static int (*early_put_chars)(u32, const char *, int);

Expand Down Expand Up @@ -482,15 +481,16 @@ struct buffer_token {
void *buf;
struct scatterlist *sg;
} u;
bool sgpages;
/* If sgpages == 0 then buf is used, else sg is used */
unsigned int sgpages;
};

static void reclaim_sg_pages(struct scatterlist *sg)
static void reclaim_sg_pages(struct scatterlist *sg, unsigned int nrpages)
{
int i;
struct page *page;

for (i = 0; i < MAX_SPLICE_PAGES; i++) {
for (i = 0; i < nrpages; i++) {
page = sg_page(&sg[i]);
if (!page)
break;
Expand All @@ -511,7 +511,7 @@ static void reclaim_consumed_buffers(struct port *port)
}
while ((tok = virtqueue_get_buf(port->out_vq, &len))) {
if (tok->sgpages)
reclaim_sg_pages(tok->u.sg);
reclaim_sg_pages(tok->u.sg, tok->sgpages);
else
kfree(tok->u.buf);
kfree(tok);
Expand Down Expand Up @@ -581,7 +581,7 @@ static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count,
tok = kmalloc(sizeof(*tok), GFP_ATOMIC);
if (!tok)
return -ENOMEM;
tok->sgpages = false;
tok->sgpages = 0;
tok->u.buf = in_buf;

sg_init_one(sg, in_buf, in_count);
Expand All @@ -597,7 +597,7 @@ static ssize_t send_pages(struct port *port, struct scatterlist *sg, int nents,
tok = kmalloc(sizeof(*tok), GFP_ATOMIC);
if (!tok)
return -ENOMEM;
tok->sgpages = true;
tok->sgpages = nents;
tok->u.sg = sg;

return __send_to_port(port, sg, nents, in_count, tok, nonblock);
Expand Down Expand Up @@ -797,6 +797,7 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,

struct sg_list {
unsigned int n;
unsigned int size;
size_t len;
struct scatterlist *sg;
};
Expand All @@ -807,7 +808,7 @@ static int pipe_to_sg(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
struct sg_list *sgl = sd->u.data;
unsigned int offset, len;

if (sgl->n == MAX_SPLICE_PAGES)
if (sgl->n == sgl->size)
return 0;

/* Try lock this page */
Expand Down Expand Up @@ -868,12 +869,12 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe,

sgl.n = 0;
sgl.len = 0;
sgl.sg = kmalloc(sizeof(struct scatterlist) * MAX_SPLICE_PAGES,
GFP_KERNEL);
sgl.size = pipe->nrbufs;
sgl.sg = kmalloc(sizeof(struct scatterlist) * sgl.size, GFP_KERNEL);
if (unlikely(!sgl.sg))
return -ENOMEM;

sg_init_table(sgl.sg, MAX_SPLICE_PAGES);
sg_init_table(sgl.sg, sgl.size);
ret = __splice_from_pipe(pipe, &sd, pipe_to_sg);
if (likely(ret > 0))
ret = send_pages(port, sgl.sg, sgl.n, sgl.len, true);
Expand Down

0 comments on commit 8ca84a5

Please sign in to comment.