diff options
author | Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> | 2012-08-09 08:31:20 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2012-09-28 01:35:12 -0400 |
commit | 8ca84a50e5b39487ea1de8809d0ee1c8474f6a5c (patch) | |
tree | 3e015a3c54606b1db785f9f1266f8d5133cc1982 /drivers/char | |
parent | d55cb6cf143ae16eaa415baab520b8eaf4a1012f (diff) |
virtio/console: Allocate scatterlist according to the current pipe size
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>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/virtio_console.c | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index b2fc2abedc79..e88f84390428 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -229,7 +229,6 @@ struct port { | |||
229 | bool guest_connected; | 229 | bool guest_connected; |
230 | }; | 230 | }; |
231 | 231 | ||
232 | #define MAX_SPLICE_PAGES 32 | ||
233 | /* This is the very early arch-specified put chars function. */ | 232 | /* This is the very early arch-specified put chars function. */ |
234 | static int (*early_put_chars)(u32, const char *, int); | 233 | static int (*early_put_chars)(u32, const char *, int); |
235 | 234 | ||
@@ -482,15 +481,16 @@ struct buffer_token { | |||
482 | void *buf; | 481 | void *buf; |
483 | struct scatterlist *sg; | 482 | struct scatterlist *sg; |
484 | } u; | 483 | } u; |
485 | bool sgpages; | 484 | /* If sgpages == 0 then buf is used, else sg is used */ |
485 | unsigned int sgpages; | ||
486 | }; | 486 | }; |
487 | 487 | ||
488 | static void reclaim_sg_pages(struct scatterlist *sg) | 488 | static void reclaim_sg_pages(struct scatterlist *sg, unsigned int nrpages) |
489 | { | 489 | { |
490 | int i; | 490 | int i; |
491 | struct page *page; | 491 | struct page *page; |
492 | 492 | ||
493 | for (i = 0; i < MAX_SPLICE_PAGES; i++) { | 493 | for (i = 0; i < nrpages; i++) { |
494 | page = sg_page(&sg[i]); | 494 | page = sg_page(&sg[i]); |
495 | if (!page) | 495 | if (!page) |
496 | break; | 496 | break; |
@@ -511,7 +511,7 @@ static void reclaim_consumed_buffers(struct port *port) | |||
511 | } | 511 | } |
512 | while ((tok = virtqueue_get_buf(port->out_vq, &len))) { | 512 | while ((tok = virtqueue_get_buf(port->out_vq, &len))) { |
513 | if (tok->sgpages) | 513 | if (tok->sgpages) |
514 | reclaim_sg_pages(tok->u.sg); | 514 | reclaim_sg_pages(tok->u.sg, tok->sgpages); |
515 | else | 515 | else |
516 | kfree(tok->u.buf); | 516 | kfree(tok->u.buf); |
517 | kfree(tok); | 517 | kfree(tok); |
@@ -581,7 +581,7 @@ static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count, | |||
581 | tok = kmalloc(sizeof(*tok), GFP_ATOMIC); | 581 | tok = kmalloc(sizeof(*tok), GFP_ATOMIC); |
582 | if (!tok) | 582 | if (!tok) |
583 | return -ENOMEM; | 583 | return -ENOMEM; |
584 | tok->sgpages = false; | 584 | tok->sgpages = 0; |
585 | tok->u.buf = in_buf; | 585 | tok->u.buf = in_buf; |
586 | 586 | ||
587 | sg_init_one(sg, in_buf, in_count); | 587 | sg_init_one(sg, in_buf, in_count); |
@@ -597,7 +597,7 @@ static ssize_t send_pages(struct port *port, struct scatterlist *sg, int nents, | |||
597 | tok = kmalloc(sizeof(*tok), GFP_ATOMIC); | 597 | tok = kmalloc(sizeof(*tok), GFP_ATOMIC); |
598 | if (!tok) | 598 | if (!tok) |
599 | return -ENOMEM; | 599 | return -ENOMEM; |
600 | tok->sgpages = true; | 600 | tok->sgpages = nents; |
601 | tok->u.sg = sg; | 601 | tok->u.sg = sg; |
602 | 602 | ||
603 | return __send_to_port(port, sg, nents, in_count, tok, nonblock); | 603 | return __send_to_port(port, sg, nents, in_count, tok, nonblock); |
@@ -797,6 +797,7 @@ out: | |||
797 | 797 | ||
798 | struct sg_list { | 798 | struct sg_list { |
799 | unsigned int n; | 799 | unsigned int n; |
800 | unsigned int size; | ||
800 | size_t len; | 801 | size_t len; |
801 | struct scatterlist *sg; | 802 | struct scatterlist *sg; |
802 | }; | 803 | }; |
@@ -807,7 +808,7 @@ static int pipe_to_sg(struct pipe_inode_info *pipe, struct pipe_buffer *buf, | |||
807 | struct sg_list *sgl = sd->u.data; | 808 | struct sg_list *sgl = sd->u.data; |
808 | unsigned int offset, len; | 809 | unsigned int offset, len; |
809 | 810 | ||
810 | if (sgl->n == MAX_SPLICE_PAGES) | 811 | if (sgl->n == sgl->size) |
811 | return 0; | 812 | return 0; |
812 | 813 | ||
813 | /* Try lock this page */ | 814 | /* Try lock this page */ |
@@ -868,12 +869,12 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe, | |||
868 | 869 | ||
869 | sgl.n = 0; | 870 | sgl.n = 0; |
870 | sgl.len = 0; | 871 | sgl.len = 0; |
871 | sgl.sg = kmalloc(sizeof(struct scatterlist) * MAX_SPLICE_PAGES, | 872 | sgl.size = pipe->nrbufs; |
872 | GFP_KERNEL); | 873 | sgl.sg = kmalloc(sizeof(struct scatterlist) * sgl.size, GFP_KERNEL); |
873 | if (unlikely(!sgl.sg)) | 874 | if (unlikely(!sgl.sg)) |
874 | return -ENOMEM; | 875 | return -ENOMEM; |
875 | 876 | ||
876 | sg_init_table(sgl.sg, MAX_SPLICE_PAGES); | 877 | sg_init_table(sgl.sg, sgl.size); |
877 | ret = __splice_from_pipe(pipe, &sd, pipe_to_sg); | 878 | ret = __splice_from_pipe(pipe, &sd, pipe_to_sg); |
878 | if (likely(ret > 0)) | 879 | if (likely(ret > 0)) |
879 | ret = send_pages(port, sgl.sg, sgl.n, sgl.len, true); | 880 | ret = send_pages(port, sgl.sg, sgl.n, sgl.len, true); |