Re: [PATCH 1/3] virtio_console:Merge struct buffer_token into struct port_buffer

2012-10-01 Thread Amit Shah
On (Wed) 26 Sep 2012 [09:48:12], Sjur BRENDELAND wrote:
> > > This merge reduces code size by unifying the approach for
> > > sending scatter-lists and regular buffers. Any type of
> > > write operation (splice, write, put_chars) will now allocate
> > > a port_buffer and send_buf() and free_buf() can always be used.
> > 
> > Thanks!
> > This looks much nicer and simpler. I just have some comments below.
> 
> OK, good to hear that you agree to this kind of change. I'll do a respin
> of this patch fixing the issues you have pointed out.
> 
> > >  static void free_buf(struct port_buffer *buf)
> > >  {
> > > + int i;
> > > +
> > >   kfree(buf->buf);
> > 
> > this should be done only when !buf->sgpages, or (see below)
> 
> Agree, I'll put this statement in an else branch to the if-statement below.

Not necessary; see my comments in another mail.

> > > -static struct port_buffer *alloc_buf(size_t buf_size)
> > > +static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t 
> > > buf_size,
> > > +  int nrbufs)
> > >  {
> > >   struct port_buffer *buf;
> > > + size_t alloc_size;
> > >
> > > - buf = kmalloc(sizeof(*buf), GFP_KERNEL);
> > > + /* Allocate buffer and the scatter list */
> > > + alloc_size = sizeof(*buf) + sizeof(struct scatterlist) * nrbufs;
> > 
> > This allocates one redundant sg entry when nrbuf > 0,
> > but I think it is OK. (just a comment)
> 
> I did this on purpose for the sake of simplicity, but I can
> change this to something like:
>alloc_size = sizeof(*buf) + sizeof(buf->sg) * max(nrbufs - 1, 1);
> 
> 
> > > + buf = kmalloc(alloc_size, GFP_ATOMIC);
> > 
> > This should be kzalloc(), or buf->buf and others are not initialized,
> > which will cause unexpected kfree bug at kfree(buf->buf) in free_buf.
> 
> Agree, kzalloc() is better in this case. 

Not really -- one thing I've picked up from Rusty is to use kmallocs
and explicitly initialise values.  Then, missing such initialisations
(like in this case) will cause tools like valgrind to show the error
pretty quickly.

> > >   if (!buf)
> > >   goto fail;
> > > - buf->buf = kzalloc(buf_size, GFP_KERNEL);
> > > +
> > > + buf->sgpages = nrbufs;
> > > + if (nrbufs > 0)
> > > + return buf;
> > > +
> > > + buf->buf = kmalloc(buf_size, GFP_ATOMIC);
> > 
> > You can also use kzalloc here as previous code does.
> > But if the reason why using kzalloc comes from the security,
> > I think kmalloc is enough here, since the host can access
> > all the guest pages anyway.
> 
> With this new patch alloc_buf() is used both for both RX and TX.
> The out_vq did previously use malloc(). But I have preserved
> the legacy behavior for the in_vq by calling memset() in function
> fill_queue().

But we're dropping the memset/kzalloc anyway.

Amit
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] virtio_console:Merge struct buffer_token into struct port_buffer

2012-10-01 Thread Amit Shah
On (Tue) 25 Sep 2012 [15:47:15], sjur.brandel...@stericsson.com wrote:
> From: Sjur Brændeland 
> 
> This merge reduces code size by unifying the approach for
> sending scatter-lists and regular buffers. Any type of
> write operation (splice, write, put_chars) will now allocate
> a port_buffer and send_buf() and free_buf() can always be used.

Thanks for this cleanup; I should've caught it at the review of the
virtio-trace patchset itself -- sorry for that.

> Signed-off-by: Sjur Brændeland 
> cc: Rusty Russell 
> cc: Michael S. Tsirkin 
> cc: Amit Shah 
> cc: Linus Walleij 
> cc: Masami Hiramatsu 
> ---
>  drivers/char/virtio_console.c |  141 
> ++---
>  1 files changed, 62 insertions(+), 79 deletions(-)
> 
> diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
> index 8ab9c3d..f4f7b04 100644
> --- a/drivers/char/virtio_console.c
> +++ b/drivers/char/virtio_console.c
> @@ -111,6 +111,11 @@ struct port_buffer {
>   size_t len;
>   /* offset in the buf from which to consume data */
>   size_t offset;
> +
> + /* If sgpages == 0 then buf is used, else sg is used */
> + unsigned int sgpages;
> +
> + struct scatterlist sg[1];
>  };
>  
>  /*
> @@ -338,23 +343,46 @@ static inline bool use_multiport(struct ports_device 
> *portdev)
>  
>  static void free_buf(struct port_buffer *buf)
>  {
> + int i;

unsigned int

> +
>   kfree(buf->buf);

buf->buf isn't set to NULL in case sgpages is > 0.  Please set
buf->buf to NULL (and initialise other fields to default values) in
alloc_buf() (and leave this as is).

> +
> + if (buf->sgpages)

This 'if' is not necessary; just having the for loop will do the right
thing.

> + for (i = 0; i < buf->sgpages; i++) {
> + struct page *page = sg_page(>sg[i]);
> + if (!page)
> + break;
> + put_page(page);
> + }
> +
>   kfree(buf);
>  }
>  
> -static struct port_buffer *alloc_buf(size_t buf_size)
> +static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size,
> +  int nrbufs)

Indentation is off.

>  {
>   struct port_buffer *buf;
> + size_t alloc_size;
>  
> - buf = kmalloc(sizeof(*buf), GFP_KERNEL);
> + /* Allocate buffer and the scatter list */
> + alloc_size = sizeof(*buf) + sizeof(struct scatterlist) * nrbufs;
> + buf = kmalloc(alloc_size, GFP_ATOMIC);

This looks hacky, along with the 'struct scatterlist sg[1]' in
port_buffer above.  Use a pointer instead?  At the least, please
include a comment in struct port_buffer mentioning sg has to be the
last element in the struct.

>   if (!buf)
>   goto fail;
> - buf->buf = kzalloc(buf_size, GFP_KERNEL);
> +
> + buf->sgpages = nrbufs;
> + if (nrbufs > 0)
> + return buf;
> +
> + buf->buf = kmalloc(buf_size, GFP_ATOMIC);

That's a lot of GFP_ATOMICS; even for the cases that don't need them.
Maybe add a gfp param that only allocates GFP_ATOMIC memory from
callers in interrupt context.  All existing code got switched to using
GFP_ATOMIC buffers as well, that's definitely not good.

>   if (!buf->buf)
>   goto free_buf;
>   buf->len = 0;
>   buf->offset = 0;
>   buf->size = buf_size;
> +
> + /* Prepare scatter buffer for sending */
> + sg_init_one(buf->sg, buf->buf, buf_size);
>   return buf;
>  
>  free_buf:
> @@ -476,52 +504,25 @@ static ssize_t send_control_msg(struct port *port, 
> unsigned int event,
>   return 0;
>  }
>  
> -struct buffer_token {
> - union {
> - void *buf;
> - struct scatterlist *sg;
> - } u;
> - /* If sgpages == 0 then buf is used, else sg is used */
> - unsigned int sgpages;
> -};
> -
> -static void reclaim_sg_pages(struct scatterlist *sg, unsigned int nrpages)
> -{
> - int i;
> - struct page *page;
> -
> - for (i = 0; i < nrpages; i++) {
> - page = sg_page([i]);
> - if (!page)
> - break;
> - put_page(page);
> - }
> - kfree(sg);
> -}
>  
>  /* Callers must take the port->outvq_lock */
>  static void reclaim_consumed_buffers(struct port *port)
>  {
> - struct buffer_token *tok;
> + struct port_buffer *buf;
>   unsigned int len;
>  
>   if (!port->portdev) {
>   /* Device has been unplugged.  vqs are already gone. */
>   return;
>   }
> - while ((tok = virtqueue_get_buf(port->out_vq, ))) {
> - if (tok->sgpages)
> - reclaim_sg_pages(tok->u.sg, tok->sgpages);
> - else
> - kfree(tok->u.buf);
> - kfree(tok);
> + while ((buf = virtqueue_get_buf(port->out_vq, ))) {
> + free_buf(buf);
>   port->outvq_full = false;
>   }
>  }
>  
> -static ssize_t __send_to_port(struct port *port, struct 

Re: [PATCH 1/3] virtio_console:Merge struct buffer_token into struct port_buffer

2012-10-01 Thread Amit Shah
On (Tue) 25 Sep 2012 [15:47:15], sjur.brandel...@stericsson.com wrote:
 From: Sjur Brændeland sjur.brandel...@stericsson.com
 
 This merge reduces code size by unifying the approach for
 sending scatter-lists and regular buffers. Any type of
 write operation (splice, write, put_chars) will now allocate
 a port_buffer and send_buf() and free_buf() can always be used.

Thanks for this cleanup; I should've caught it at the review of the
virtio-trace patchset itself -- sorry for that.

 Signed-off-by: Sjur Brændeland sjur.brandel...@stericsson.com
 cc: Rusty Russell ru...@rustcorp.com.au
 cc: Michael S. Tsirkin m...@redhat.com
 cc: Amit Shah amit.s...@redhat.com
 cc: Linus Walleij linus.wall...@linaro.org
 cc: Masami Hiramatsu masami.hiramatsu...@hitachi.com
 ---
  drivers/char/virtio_console.c |  141 
 ++---
  1 files changed, 62 insertions(+), 79 deletions(-)
 
 diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
 index 8ab9c3d..f4f7b04 100644
 --- a/drivers/char/virtio_console.c
 +++ b/drivers/char/virtio_console.c
 @@ -111,6 +111,11 @@ struct port_buffer {
   size_t len;
   /* offset in the buf from which to consume data */
   size_t offset;
 +
 + /* If sgpages == 0 then buf is used, else sg is used */
 + unsigned int sgpages;
 +
 + struct scatterlist sg[1];
  };
  
  /*
 @@ -338,23 +343,46 @@ static inline bool use_multiport(struct ports_device 
 *portdev)
  
  static void free_buf(struct port_buffer *buf)
  {
 + int i;

unsigned int

 +
   kfree(buf-buf);

buf-buf isn't set to NULL in case sgpages is  0.  Please set
buf-buf to NULL (and initialise other fields to default values) in
alloc_buf() (and leave this as is).

 +
 + if (buf-sgpages)

This 'if' is not necessary; just having the for loop will do the right
thing.

 + for (i = 0; i  buf-sgpages; i++) {
 + struct page *page = sg_page(buf-sg[i]);
 + if (!page)
 + break;
 + put_page(page);
 + }
 +
   kfree(buf);
  }
  
 -static struct port_buffer *alloc_buf(size_t buf_size)
 +static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size,
 +  int nrbufs)

Indentation is off.

  {
   struct port_buffer *buf;
 + size_t alloc_size;
  
 - buf = kmalloc(sizeof(*buf), GFP_KERNEL);
 + /* Allocate buffer and the scatter list */
 + alloc_size = sizeof(*buf) + sizeof(struct scatterlist) * nrbufs;
 + buf = kmalloc(alloc_size, GFP_ATOMIC);

This looks hacky, along with the 'struct scatterlist sg[1]' in
port_buffer above.  Use a pointer instead?  At the least, please
include a comment in struct port_buffer mentioning sg has to be the
last element in the struct.

   if (!buf)
   goto fail;
 - buf-buf = kzalloc(buf_size, GFP_KERNEL);
 +
 + buf-sgpages = nrbufs;
 + if (nrbufs  0)
 + return buf;
 +
 + buf-buf = kmalloc(buf_size, GFP_ATOMIC);

That's a lot of GFP_ATOMICS; even for the cases that don't need them.
Maybe add a gfp param that only allocates GFP_ATOMIC memory from
callers in interrupt context.  All existing code got switched to using
GFP_ATOMIC buffers as well, that's definitely not good.

   if (!buf-buf)
   goto free_buf;
   buf-len = 0;
   buf-offset = 0;
   buf-size = buf_size;
 +
 + /* Prepare scatter buffer for sending */
 + sg_init_one(buf-sg, buf-buf, buf_size);
   return buf;
  
  free_buf:
 @@ -476,52 +504,25 @@ static ssize_t send_control_msg(struct port *port, 
 unsigned int event,
   return 0;
  }
  
 -struct buffer_token {
 - union {
 - void *buf;
 - struct scatterlist *sg;
 - } u;
 - /* If sgpages == 0 then buf is used, else sg is used */
 - unsigned int sgpages;
 -};
 -
 -static void reclaim_sg_pages(struct scatterlist *sg, unsigned int nrpages)
 -{
 - int i;
 - struct page *page;
 -
 - for (i = 0; i  nrpages; i++) {
 - page = sg_page(sg[i]);
 - if (!page)
 - break;
 - put_page(page);
 - }
 - kfree(sg);
 -}
  
  /* Callers must take the port-outvq_lock */
  static void reclaim_consumed_buffers(struct port *port)
  {
 - struct buffer_token *tok;
 + struct port_buffer *buf;
   unsigned int len;
  
   if (!port-portdev) {
   /* Device has been unplugged.  vqs are already gone. */
   return;
   }
 - while ((tok = virtqueue_get_buf(port-out_vq, len))) {
 - if (tok-sgpages)
 - reclaim_sg_pages(tok-u.sg, tok-sgpages);
 - else
 - kfree(tok-u.buf);
 - kfree(tok);
 + while ((buf = virtqueue_get_buf(port-out_vq, len))) {
 + free_buf(buf);
   port-outvq_full = false;
   }
  }
  
 -static ssize_t __send_to_port(struct port 

Re: [PATCH 1/3] virtio_console:Merge struct buffer_token into struct port_buffer

2012-10-01 Thread Amit Shah
On (Wed) 26 Sep 2012 [09:48:12], Sjur BRENDELAND wrote:
   This merge reduces code size by unifying the approach for
   sending scatter-lists and regular buffers. Any type of
   write operation (splice, write, put_chars) will now allocate
   a port_buffer and send_buf() and free_buf() can always be used.
  
  Thanks!
  This looks much nicer and simpler. I just have some comments below.
 
 OK, good to hear that you agree to this kind of change. I'll do a respin
 of this patch fixing the issues you have pointed out.
 
static void free_buf(struct port_buffer *buf)
{
   + int i;
   +
 kfree(buf-buf);
  
  this should be done only when !buf-sgpages, or (see below)
 
 Agree, I'll put this statement in an else branch to the if-statement below.

Not necessary; see my comments in another mail.

   -static struct port_buffer *alloc_buf(size_t buf_size)
   +static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t 
   buf_size,
   +  int nrbufs)
{
 struct port_buffer *buf;
   + size_t alloc_size;
  
   - buf = kmalloc(sizeof(*buf), GFP_KERNEL);
   + /* Allocate buffer and the scatter list */
   + alloc_size = sizeof(*buf) + sizeof(struct scatterlist) * nrbufs;
  
  This allocates one redundant sg entry when nrbuf  0,
  but I think it is OK. (just a comment)
 
 I did this on purpose for the sake of simplicity, but I can
 change this to something like:
alloc_size = sizeof(*buf) + sizeof(buf-sg) * max(nrbufs - 1, 1);
 
 
   + buf = kmalloc(alloc_size, GFP_ATOMIC);
  
  This should be kzalloc(), or buf-buf and others are not initialized,
  which will cause unexpected kfree bug at kfree(buf-buf) in free_buf.
 
 Agree, kzalloc() is better in this case. 

Not really -- one thing I've picked up from Rusty is to use kmallocs
and explicitly initialise values.  Then, missing such initialisations
(like in this case) will cause tools like valgrind to show the error
pretty quickly.

 if (!buf)
 goto fail;
   - buf-buf = kzalloc(buf_size, GFP_KERNEL);
   +
   + buf-sgpages = nrbufs;
   + if (nrbufs  0)
   + return buf;
   +
   + buf-buf = kmalloc(buf_size, GFP_ATOMIC);
  
  You can also use kzalloc here as previous code does.
  But if the reason why using kzalloc comes from the security,
  I think kmalloc is enough here, since the host can access
  all the guest pages anyway.
 
 With this new patch alloc_buf() is used both for both RX and TX.
 The out_vq did previously use malloc(). But I have preserved
 the legacy behavior for the in_vq by calling memset() in function
 fill_queue().

But we're dropping the memset/kzalloc anyway.

Amit
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


RE: [PATCH 1/3] virtio_console:Merge struct buffer_token into struct port_buffer

2012-09-26 Thread Rusty Russell
Sjur BRENDELAND  writes:
>> This allocates one redundant sg entry when nrbuf > 0,
>> but I think it is OK. (just a comment)
>
> I did this on purpose for the sake of simplicity, but I can
> change this to something like:
>alloc_size = sizeof(*buf) + sizeof(buf->sg) * max(nrbufs - 1, 1);

That's why we use [0] in the definition (a GCC extension).

Cheers,
Rusty.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] virtio_console:Merge struct buffer_token into struct port_buffer

2012-09-26 Thread Masami Hiramatsu
(2012/09/26 16:48), Sjur BRENDELAND wrote:
>>> -static struct port_buffer *alloc_buf(size_t buf_size)
>>> +static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size,
>>> +int nrbufs)
>>>  {
>>> struct port_buffer *buf;
>>> +   size_t alloc_size;
>>>
>>> -   buf = kmalloc(sizeof(*buf), GFP_KERNEL);
>>> +   /* Allocate buffer and the scatter list */
>>> +   alloc_size = sizeof(*buf) + sizeof(struct scatterlist) * nrbufs;
>>
>> This allocates one redundant sg entry when nrbuf > 0,
>> but I think it is OK. (just a comment)
> 
> I did this on purpose for the sake of simplicity, but I can
> change this to something like:
>alloc_size = sizeof(*buf) + sizeof(buf->sg) * max(nrbufs - 1, 1);

You wouldn't need to change that. I think current code is enough simple
and reasonable. :)

Thanks!

-- 
Masami HIRAMATSU
Software Platform Research Dept. Linux Technology Center
Hitachi, Ltd., Yokohama Research Laboratory
E-mail: masami.hiramatsu...@hitachi.com


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


RE: [PATCH 1/3] virtio_console:Merge struct buffer_token into struct port_buffer

2012-09-26 Thread Sjur BRENDELAND
> > This merge reduces code size by unifying the approach for
> > sending scatter-lists and regular buffers. Any type of
> > write operation (splice, write, put_chars) will now allocate
> > a port_buffer and send_buf() and free_buf() can always be used.
> 
> Thanks!
> This looks much nicer and simpler. I just have some comments below.

OK, good to hear that you agree to this kind of change. I'll do a respin
of this patch fixing the issues you have pointed out.

> >  static void free_buf(struct port_buffer *buf)
> >  {
> > +   int i;
> > +
> > kfree(buf->buf);
> 
> this should be done only when !buf->sgpages, or (see below)

Agree, I'll put this statement in an else branch to the if-statement below.

> 
> > +
> > +   if (buf->sgpages)
> > +   for (i = 0; i < buf->sgpages; i++) {
> > +   struct page *page = sg_page(>sg[i]);
> > +   if (!page)
> > +   break;
> > +   put_page(page);
> > +   }
> > +
> > kfree(buf);
> >  }
> >
> > -static struct port_buffer *alloc_buf(size_t buf_size)
> > +static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size,
> > +int nrbufs)
> >  {
> > struct port_buffer *buf;
> > +   size_t alloc_size;
> >
> > -   buf = kmalloc(sizeof(*buf), GFP_KERNEL);
> > +   /* Allocate buffer and the scatter list */
> > +   alloc_size = sizeof(*buf) + sizeof(struct scatterlist) * nrbufs;
> 
> This allocates one redundant sg entry when nrbuf > 0,
> but I think it is OK. (just a comment)

I did this on purpose for the sake of simplicity, but I can
change this to something like:
 alloc_size = sizeof(*buf) + sizeof(buf->sg) * max(nrbufs - 1, 1);


> > +   buf = kmalloc(alloc_size, GFP_ATOMIC);
> 
> This should be kzalloc(), or buf->buf and others are not initialized,
> which will cause unexpected kfree bug at kfree(buf->buf) in free_buf.

Agree, kzalloc() is better in this case. 

> > if (!buf)
> > goto fail;
> > -   buf->buf = kzalloc(buf_size, GFP_KERNEL);
> > +
> > +   buf->sgpages = nrbufs;
> > +   if (nrbufs > 0)
> > +   return buf;
> > +
> > +   buf->buf = kmalloc(buf_size, GFP_ATOMIC);
> 
> You can also use kzalloc here as previous code does.
> But if the reason why using kzalloc comes from the security,
> I think kmalloc is enough here, since the host can access
> all the guest pages anyway.

With this new patch alloc_buf() is used both for both RX and TX.
The out_vq did previously use malloc(). But I have preserved
the legacy behavior for the in_vq by calling memset() in function
fill_queue().

Thanks,
Sjur


RE: [PATCH 1/3] virtio_console:Merge struct buffer_token into struct port_buffer

2012-09-26 Thread Sjur BRENDELAND
  This merge reduces code size by unifying the approach for
  sending scatter-lists and regular buffers. Any type of
  write operation (splice, write, put_chars) will now allocate
  a port_buffer and send_buf() and free_buf() can always be used.
 
 Thanks!
 This looks much nicer and simpler. I just have some comments below.

OK, good to hear that you agree to this kind of change. I'll do a respin
of this patch fixing the issues you have pointed out.

   static void free_buf(struct port_buffer *buf)
   {
  +   int i;
  +
  kfree(buf-buf);
 
 this should be done only when !buf-sgpages, or (see below)

Agree, I'll put this statement in an else branch to the if-statement below.

 
  +
  +   if (buf-sgpages)
  +   for (i = 0; i  buf-sgpages; i++) {
  +   struct page *page = sg_page(buf-sg[i]);
  +   if (!page)
  +   break;
  +   put_page(page);
  +   }
  +
  kfree(buf);
   }
 
  -static struct port_buffer *alloc_buf(size_t buf_size)
  +static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size,
  +int nrbufs)
   {
  struct port_buffer *buf;
  +   size_t alloc_size;
 
  -   buf = kmalloc(sizeof(*buf), GFP_KERNEL);
  +   /* Allocate buffer and the scatter list */
  +   alloc_size = sizeof(*buf) + sizeof(struct scatterlist) * nrbufs;
 
 This allocates one redundant sg entry when nrbuf  0,
 but I think it is OK. (just a comment)

I did this on purpose for the sake of simplicity, but I can
change this to something like:
 alloc_size = sizeof(*buf) + sizeof(buf-sg) * max(nrbufs - 1, 1);


  +   buf = kmalloc(alloc_size, GFP_ATOMIC);
 
 This should be kzalloc(), or buf-buf and others are not initialized,
 which will cause unexpected kfree bug at kfree(buf-buf) in free_buf.

Agree, kzalloc() is better in this case. 

  if (!buf)
  goto fail;
  -   buf-buf = kzalloc(buf_size, GFP_KERNEL);
  +
  +   buf-sgpages = nrbufs;
  +   if (nrbufs  0)
  +   return buf;
  +
  +   buf-buf = kmalloc(buf_size, GFP_ATOMIC);
 
 You can also use kzalloc here as previous code does.
 But if the reason why using kzalloc comes from the security,
 I think kmalloc is enough here, since the host can access
 all the guest pages anyway.

With this new patch alloc_buf() is used both for both RX and TX.
The out_vq did previously use malloc(). But I have preserved
the legacy behavior for the in_vq by calling memset() in function
fill_queue().

Thanks,
Sjur


Re: [PATCH 1/3] virtio_console:Merge struct buffer_token into struct port_buffer

2012-09-26 Thread Masami Hiramatsu
(2012/09/26 16:48), Sjur BRENDELAND wrote:
 -static struct port_buffer *alloc_buf(size_t buf_size)
 +static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size,
 +int nrbufs)
  {
 struct port_buffer *buf;
 +   size_t alloc_size;

 -   buf = kmalloc(sizeof(*buf), GFP_KERNEL);
 +   /* Allocate buffer and the scatter list */
 +   alloc_size = sizeof(*buf) + sizeof(struct scatterlist) * nrbufs;

 This allocates one redundant sg entry when nrbuf  0,
 but I think it is OK. (just a comment)
 
 I did this on purpose for the sake of simplicity, but I can
 change this to something like:
alloc_size = sizeof(*buf) + sizeof(buf-sg) * max(nrbufs - 1, 1);

You wouldn't need to change that. I think current code is enough simple
and reasonable. :)

Thanks!

-- 
Masami HIRAMATSU
Software Platform Research Dept. Linux Technology Center
Hitachi, Ltd., Yokohama Research Laboratory
E-mail: masami.hiramatsu...@hitachi.com


--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


RE: [PATCH 1/3] virtio_console:Merge struct buffer_token into struct port_buffer

2012-09-26 Thread Rusty Russell
Sjur BRENDELAND sjur.brandel...@stericsson.com writes:
 This allocates one redundant sg entry when nrbuf  0,
 but I think it is OK. (just a comment)

 I did this on purpose for the sake of simplicity, but I can
 change this to something like:
alloc_size = sizeof(*buf) + sizeof(buf-sg) * max(nrbufs - 1, 1);

That's why we use [0] in the definition (a GCC extension).

Cheers,
Rusty.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] virtio_console:Merge struct buffer_token into struct port_buffer

2012-09-25 Thread Masami Hiramatsu
(2012/09/25 22:47), sjur.brandel...@stericsson.com wrote:
> From: Sjur Brændeland 
> 
> This merge reduces code size by unifying the approach for
> sending scatter-lists and regular buffers. Any type of
> write operation (splice, write, put_chars) will now allocate
> a port_buffer and send_buf() and free_buf() can always be used.

Thanks!
This looks much nicer and simpler. I just have some comments below.

> Signed-off-by: Sjur Brændeland 
> cc: Rusty Russell 
> cc: Michael S. Tsirkin 
> cc: Amit Shah 
> cc: Linus Walleij 
> cc: Masami Hiramatsu 
> ---
>  drivers/char/virtio_console.c |  141 
> ++---
>  1 files changed, 62 insertions(+), 79 deletions(-)
> 
> diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
> index 8ab9c3d..f4f7b04 100644
> --- a/drivers/char/virtio_console.c
> +++ b/drivers/char/virtio_console.c
> @@ -111,6 +111,11 @@ struct port_buffer {
>   size_t len;
>   /* offset in the buf from which to consume data */
>   size_t offset;
> +
> + /* If sgpages == 0 then buf is used, else sg is used */
> + unsigned int sgpages;
> +
> + struct scatterlist sg[1];
>  };
>  
>  /*
> @@ -338,23 +343,46 @@ static inline bool use_multiport(struct ports_device 
> *portdev)
>  
>  static void free_buf(struct port_buffer *buf)
>  {
> + int i;
> +
>   kfree(buf->buf);

this should be done only when !buf->sgpages, or (see below)

> +
> + if (buf->sgpages)
> + for (i = 0; i < buf->sgpages; i++) {
> + struct page *page = sg_page(>sg[i]);
> + if (!page)
> + break;
> + put_page(page);
> + }
> +
>   kfree(buf);
>  }
>  
> -static struct port_buffer *alloc_buf(size_t buf_size)
> +static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size,
> +  int nrbufs)
>  {
>   struct port_buffer *buf;
> + size_t alloc_size;
>  
> - buf = kmalloc(sizeof(*buf), GFP_KERNEL);
> + /* Allocate buffer and the scatter list */
> + alloc_size = sizeof(*buf) + sizeof(struct scatterlist) * nrbufs;

This allocates one redundant sg entry when nrbuf > 0,
but I think it is OK. (just a comment)

> + buf = kmalloc(alloc_size, GFP_ATOMIC);

This should be kzalloc(), or buf->buf and others are not initialized,
which will cause unexpected kfree bug at kfree(buf->buf) in free_buf.

>   if (!buf)
>   goto fail;
> - buf->buf = kzalloc(buf_size, GFP_KERNEL);
> +
> + buf->sgpages = nrbufs;
> + if (nrbufs > 0)
> + return buf;
> +
> + buf->buf = kmalloc(buf_size, GFP_ATOMIC);

You can also use kzalloc here as previous code does.
But if the reason why using kzalloc comes from the security,
I think kmalloc is enough here, since the host can access
all the guest pages anyway.

>   if (!buf->buf)
>   goto free_buf;
>   buf->len = 0;
>   buf->offset = 0;
>   buf->size = buf_size;
> +
> + /* Prepare scatter buffer for sending */
> + sg_init_one(buf->sg, buf->buf, buf_size);
>   return buf;
>  
>  free_buf:

Thank you,


-- 
Masami HIRAMATSU
Software Platform Research Dept. Linux Technology Center
Hitachi, Ltd., Yokohama Research Laboratory
E-mail: masami.hiramatsu...@hitachi.com


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/3] virtio_console:Merge struct buffer_token into struct port_buffer

2012-09-25 Thread sjur . brandeland
From: Sjur Brændeland 

This merge reduces code size by unifying the approach for
sending scatter-lists and regular buffers. Any type of
write operation (splice, write, put_chars) will now allocate
a port_buffer and send_buf() and free_buf() can always be used.

Signed-off-by: Sjur Brændeland 
cc: Rusty Russell 
cc: Michael S. Tsirkin 
cc: Amit Shah 
cc: Linus Walleij 
cc: Masami Hiramatsu 
---
 drivers/char/virtio_console.c |  141 ++---
 1 files changed, 62 insertions(+), 79 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 8ab9c3d..f4f7b04 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -111,6 +111,11 @@ struct port_buffer {
size_t len;
/* offset in the buf from which to consume data */
size_t offset;
+
+   /* If sgpages == 0 then buf is used, else sg is used */
+   unsigned int sgpages;
+
+   struct scatterlist sg[1];
 };
 
 /*
@@ -338,23 +343,46 @@ static inline bool use_multiport(struct ports_device 
*portdev)
 
 static void free_buf(struct port_buffer *buf)
 {
+   int i;
+
kfree(buf->buf);
+
+   if (buf->sgpages)
+   for (i = 0; i < buf->sgpages; i++) {
+   struct page *page = sg_page(>sg[i]);
+   if (!page)
+   break;
+   put_page(page);
+   }
+
kfree(buf);
 }
 
-static struct port_buffer *alloc_buf(size_t buf_size)
+static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size,
+int nrbufs)
 {
struct port_buffer *buf;
+   size_t alloc_size;
 
-   buf = kmalloc(sizeof(*buf), GFP_KERNEL);
+   /* Allocate buffer and the scatter list */
+   alloc_size = sizeof(*buf) + sizeof(struct scatterlist) * nrbufs;
+   buf = kmalloc(alloc_size, GFP_ATOMIC);
if (!buf)
goto fail;
-   buf->buf = kzalloc(buf_size, GFP_KERNEL);
+
+   buf->sgpages = nrbufs;
+   if (nrbufs > 0)
+   return buf;
+
+   buf->buf = kmalloc(buf_size, GFP_ATOMIC);
if (!buf->buf)
goto free_buf;
buf->len = 0;
buf->offset = 0;
buf->size = buf_size;
+
+   /* Prepare scatter buffer for sending */
+   sg_init_one(buf->sg, buf->buf, buf_size);
return buf;
 
 free_buf:
@@ -476,52 +504,25 @@ static ssize_t send_control_msg(struct port *port, 
unsigned int event,
return 0;
 }
 
-struct buffer_token {
-   union {
-   void *buf;
-   struct scatterlist *sg;
-   } u;
-   /* If sgpages == 0 then buf is used, else sg is used */
-   unsigned int sgpages;
-};
-
-static void reclaim_sg_pages(struct scatterlist *sg, unsigned int nrpages)
-{
-   int i;
-   struct page *page;
-
-   for (i = 0; i < nrpages; i++) {
-   page = sg_page([i]);
-   if (!page)
-   break;
-   put_page(page);
-   }
-   kfree(sg);
-}
 
 /* Callers must take the port->outvq_lock */
 static void reclaim_consumed_buffers(struct port *port)
 {
-   struct buffer_token *tok;
+   struct port_buffer *buf;
unsigned int len;
 
if (!port->portdev) {
/* Device has been unplugged.  vqs are already gone. */
return;
}
-   while ((tok = virtqueue_get_buf(port->out_vq, ))) {
-   if (tok->sgpages)
-   reclaim_sg_pages(tok->u.sg, tok->sgpages);
-   else
-   kfree(tok->u.buf);
-   kfree(tok);
+   while ((buf = virtqueue_get_buf(port->out_vq, ))) {
+   free_buf(buf);
port->outvq_full = false;
}
 }
 
-static ssize_t __send_to_port(struct port *port, struct scatterlist *sg,
- int nents, size_t in_count,
- struct buffer_token *tok, bool nonblock)
+static ssize_t send_buf(struct port *port, struct port_buffer *buf, int nents,
+ size_t in_count, bool nonblock)
 {
struct virtqueue *out_vq;
ssize_t ret;
@@ -534,7 +535,7 @@ static ssize_t __send_to_port(struct port *port, struct 
scatterlist *sg,
 
reclaim_consumed_buffers(port);
 
-   ret = virtqueue_add_buf(out_vq, sg, nents, 0, tok, GFP_ATOMIC);
+   ret = virtqueue_add_buf(out_vq, buf->sg, nents, 0, buf, GFP_ATOMIC);
 
/* Tell Host to go! */
virtqueue_kick(out_vq);
@@ -559,8 +560,11 @@ static ssize_t __send_to_port(struct port *port, struct 
scatterlist *sg,
 * we need to kmalloc a GFP_ATOMIC buffer each time the
 * console driver writes something out.
 */
-   while (!virtqueue_get_buf(out_vq, ))
+   for (buf = virtqueue_get_buf(out_vq, ); !buf;
+buf = virtqueue_get_buf(out_vq, ))
cpu_relax();
+
+   

[PATCH 1/3] virtio_console:Merge struct buffer_token into struct port_buffer

2012-09-25 Thread sjur . brandeland
From: Sjur Brændeland sjur.brandel...@stericsson.com

This merge reduces code size by unifying the approach for
sending scatter-lists and regular buffers. Any type of
write operation (splice, write, put_chars) will now allocate
a port_buffer and send_buf() and free_buf() can always be used.

Signed-off-by: Sjur Brændeland sjur.brandel...@stericsson.com
cc: Rusty Russell ru...@rustcorp.com.au
cc: Michael S. Tsirkin m...@redhat.com
cc: Amit Shah amit.s...@redhat.com
cc: Linus Walleij linus.wall...@linaro.org
cc: Masami Hiramatsu masami.hiramatsu...@hitachi.com
---
 drivers/char/virtio_console.c |  141 ++---
 1 files changed, 62 insertions(+), 79 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 8ab9c3d..f4f7b04 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -111,6 +111,11 @@ struct port_buffer {
size_t len;
/* offset in the buf from which to consume data */
size_t offset;
+
+   /* If sgpages == 0 then buf is used, else sg is used */
+   unsigned int sgpages;
+
+   struct scatterlist sg[1];
 };
 
 /*
@@ -338,23 +343,46 @@ static inline bool use_multiport(struct ports_device 
*portdev)
 
 static void free_buf(struct port_buffer *buf)
 {
+   int i;
+
kfree(buf-buf);
+
+   if (buf-sgpages)
+   for (i = 0; i  buf-sgpages; i++) {
+   struct page *page = sg_page(buf-sg[i]);
+   if (!page)
+   break;
+   put_page(page);
+   }
+
kfree(buf);
 }
 
-static struct port_buffer *alloc_buf(size_t buf_size)
+static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size,
+int nrbufs)
 {
struct port_buffer *buf;
+   size_t alloc_size;
 
-   buf = kmalloc(sizeof(*buf), GFP_KERNEL);
+   /* Allocate buffer and the scatter list */
+   alloc_size = sizeof(*buf) + sizeof(struct scatterlist) * nrbufs;
+   buf = kmalloc(alloc_size, GFP_ATOMIC);
if (!buf)
goto fail;
-   buf-buf = kzalloc(buf_size, GFP_KERNEL);
+
+   buf-sgpages = nrbufs;
+   if (nrbufs  0)
+   return buf;
+
+   buf-buf = kmalloc(buf_size, GFP_ATOMIC);
if (!buf-buf)
goto free_buf;
buf-len = 0;
buf-offset = 0;
buf-size = buf_size;
+
+   /* Prepare scatter buffer for sending */
+   sg_init_one(buf-sg, buf-buf, buf_size);
return buf;
 
 free_buf:
@@ -476,52 +504,25 @@ static ssize_t send_control_msg(struct port *port, 
unsigned int event,
return 0;
 }
 
-struct buffer_token {
-   union {
-   void *buf;
-   struct scatterlist *sg;
-   } u;
-   /* If sgpages == 0 then buf is used, else sg is used */
-   unsigned int sgpages;
-};
-
-static void reclaim_sg_pages(struct scatterlist *sg, unsigned int nrpages)
-{
-   int i;
-   struct page *page;
-
-   for (i = 0; i  nrpages; i++) {
-   page = sg_page(sg[i]);
-   if (!page)
-   break;
-   put_page(page);
-   }
-   kfree(sg);
-}
 
 /* Callers must take the port-outvq_lock */
 static void reclaim_consumed_buffers(struct port *port)
 {
-   struct buffer_token *tok;
+   struct port_buffer *buf;
unsigned int len;
 
if (!port-portdev) {
/* Device has been unplugged.  vqs are already gone. */
return;
}
-   while ((tok = virtqueue_get_buf(port-out_vq, len))) {
-   if (tok-sgpages)
-   reclaim_sg_pages(tok-u.sg, tok-sgpages);
-   else
-   kfree(tok-u.buf);
-   kfree(tok);
+   while ((buf = virtqueue_get_buf(port-out_vq, len))) {
+   free_buf(buf);
port-outvq_full = false;
}
 }
 
-static ssize_t __send_to_port(struct port *port, struct scatterlist *sg,
- int nents, size_t in_count,
- struct buffer_token *tok, bool nonblock)
+static ssize_t send_buf(struct port *port, struct port_buffer *buf, int nents,
+ size_t in_count, bool nonblock)
 {
struct virtqueue *out_vq;
ssize_t ret;
@@ -534,7 +535,7 @@ static ssize_t __send_to_port(struct port *port, struct 
scatterlist *sg,
 
reclaim_consumed_buffers(port);
 
-   ret = virtqueue_add_buf(out_vq, sg, nents, 0, tok, GFP_ATOMIC);
+   ret = virtqueue_add_buf(out_vq, buf-sg, nents, 0, buf, GFP_ATOMIC);
 
/* Tell Host to go! */
virtqueue_kick(out_vq);
@@ -559,8 +560,11 @@ static ssize_t __send_to_port(struct port *port, struct 
scatterlist *sg,
 * we need to kmalloc a GFP_ATOMIC buffer each time the
 * console driver writes something out.
 */
-   while 

Re: [PATCH 1/3] virtio_console:Merge struct buffer_token into struct port_buffer

2012-09-25 Thread Masami Hiramatsu
(2012/09/25 22:47), sjur.brandel...@stericsson.com wrote:
 From: Sjur Brændeland sjur.brandel...@stericsson.com
 
 This merge reduces code size by unifying the approach for
 sending scatter-lists and regular buffers. Any type of
 write operation (splice, write, put_chars) will now allocate
 a port_buffer and send_buf() and free_buf() can always be used.

Thanks!
This looks much nicer and simpler. I just have some comments below.

 Signed-off-by: Sjur Brændeland sjur.brandel...@stericsson.com
 cc: Rusty Russell ru...@rustcorp.com.au
 cc: Michael S. Tsirkin m...@redhat.com
 cc: Amit Shah amit.s...@redhat.com
 cc: Linus Walleij linus.wall...@linaro.org
 cc: Masami Hiramatsu masami.hiramatsu...@hitachi.com
 ---
  drivers/char/virtio_console.c |  141 
 ++---
  1 files changed, 62 insertions(+), 79 deletions(-)
 
 diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
 index 8ab9c3d..f4f7b04 100644
 --- a/drivers/char/virtio_console.c
 +++ b/drivers/char/virtio_console.c
 @@ -111,6 +111,11 @@ struct port_buffer {
   size_t len;
   /* offset in the buf from which to consume data */
   size_t offset;
 +
 + /* If sgpages == 0 then buf is used, else sg is used */
 + unsigned int sgpages;
 +
 + struct scatterlist sg[1];
  };
  
  /*
 @@ -338,23 +343,46 @@ static inline bool use_multiport(struct ports_device 
 *portdev)
  
  static void free_buf(struct port_buffer *buf)
  {
 + int i;
 +
   kfree(buf-buf);

this should be done only when !buf-sgpages, or (see below)

 +
 + if (buf-sgpages)
 + for (i = 0; i  buf-sgpages; i++) {
 + struct page *page = sg_page(buf-sg[i]);
 + if (!page)
 + break;
 + put_page(page);
 + }
 +
   kfree(buf);
  }
  
 -static struct port_buffer *alloc_buf(size_t buf_size)
 +static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size,
 +  int nrbufs)
  {
   struct port_buffer *buf;
 + size_t alloc_size;
  
 - buf = kmalloc(sizeof(*buf), GFP_KERNEL);
 + /* Allocate buffer and the scatter list */
 + alloc_size = sizeof(*buf) + sizeof(struct scatterlist) * nrbufs;

This allocates one redundant sg entry when nrbuf  0,
but I think it is OK. (just a comment)

 + buf = kmalloc(alloc_size, GFP_ATOMIC);

This should be kzalloc(), or buf-buf and others are not initialized,
which will cause unexpected kfree bug at kfree(buf-buf) in free_buf.

   if (!buf)
   goto fail;
 - buf-buf = kzalloc(buf_size, GFP_KERNEL);
 +
 + buf-sgpages = nrbufs;
 + if (nrbufs  0)
 + return buf;
 +
 + buf-buf = kmalloc(buf_size, GFP_ATOMIC);

You can also use kzalloc here as previous code does.
But if the reason why using kzalloc comes from the security,
I think kmalloc is enough here, since the host can access
all the guest pages anyway.

   if (!buf-buf)
   goto free_buf;
   buf-len = 0;
   buf-offset = 0;
   buf-size = buf_size;
 +
 + /* Prepare scatter buffer for sending */
 + sg_init_one(buf-sg, buf-buf, buf_size);
   return buf;
  
  free_buf:

Thank you,


-- 
Masami HIRAMATSU
Software Platform Research Dept. Linux Technology Center
Hitachi, Ltd., Yokohama Research Laboratory
E-mail: masami.hiramatsu...@hitachi.com


--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/