[CRIU] [PATCH 11/15] bfd: Multiple buffers management (v2)

Andrew Vagin avagin at parallels.com
Mon Sep 29 03:42:31 PDT 2014


On Mon, Sep 29, 2014 at 02:39:35PM +0400, Pavel Emelyanov wrote:
> I plan to re-use the bfd engine for images buffering. Right
> now this engine uses one buffer that gets reused by all
> bfdopen()-s. This works for current usage (one-by-pne proc
> files access), but for images we'll need more buffers.
> 
> So this patch just puts buffers in a list and organizes a
> stupid R-R with refill on it.
> 
> v2:
>   Check for buffer allocation errors
>   Print buffer mem pointer in debug

Acked-by: Andrew Vagin <avagin at parallels.com>

Thanks.

> 
> Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
> Signed-off-by: root <root at localhost.localdomain>
> ---
>  bfd.c         | 63 +++++++++++++++++++++++++++++++++++++++++++----------------
>  include/bfd.h |  2 ++
>  2 files changed, 48 insertions(+), 17 deletions(-)
> 
> diff --git a/bfd.c b/bfd.c
> index 34030f5..87ec945 100644
> --- a/bfd.c
> +++ b/bfd.c
> @@ -7,6 +7,8 @@
>  
>  #include "log.h"
>  #include "bfd.h"
> +#include "list.h"
> +#include "xmalloc.h"
>  #include "asm-generic/page.h"
>  
>  /*
> @@ -15,43 +17,70 @@
>   */
>  #define BUFSIZE	(PAGE_SIZE)
>  
> -/*
> - * XXX currently CRIU doesn't open several files
> - * at once, so we can have just one buffer.
> - */
> -static char *buf;
> -static bool buf_busy;
> +struct bfd_buf {
> +	char *mem;
> +	struct list_head l;
> +};
> +
> +static LIST_HEAD(bufs);
> +
> +#define BUFBATCH	(16)
>  
>  static int buf_get(struct xbuf *xb)
>  {
> -	if (buf_busy) {
> -		pr_err("bfd: Buffer busy\n");
> -		return -1;
> -	}
> +	struct bfd_buf *b;
>  
> -	if (!buf) {
> -		buf = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE,
> +	if (list_empty(&bufs)) {
> +		void *mem;
> +		int i;
> +
> +		pr_debug("BUF++\n");
> +		mem = mmap(NULL, BUFBATCH * BUFSIZE, PROT_READ | PROT_WRITE,
>  				MAP_PRIVATE | MAP_ANON, 0, 0);
> -		if (buf == MAP_FAILED) {
> +		if (mem == MAP_FAILED) {
>  			pr_perror("bfd: No buf");
>  			return -1;
>  		}
> +
> +		for (i = 0; i < BUFBATCH; i++) {
> +			b = xmalloc(sizeof(*b));
> +			if (!b) {
> +				if (i == 0) {
> +					pr_err("No buffer for bfd\n");
> +					return -1;
> +				}
> +
> +				pr_warn("BFD buffers partial refil!\n");
> +				break;
> +			}
> +
> +			b->mem = mem + i * BUFSIZE;
> +			list_add_tail(&b->l, &bufs);
> +		}
>  	}
>  
> -	buf_busy = true;
> -	xb->mem = buf;
> -	xb->pos = buf;
> +	b = list_first_entry(&bufs, struct bfd_buf, l);
> +	list_del_init(&b->l);
> +
> +	xb->mem = b->mem;
> +	xb->pos = xb->mem;
>  	xb->bleft = 0;
> +	xb->buf = b;
> +	pr_debug("BUF %p <\n", xb->mem);
>  	return 0;
>  }
>  
>  static void buf_put(struct xbuf *xb)
>  {
> -	buf_busy = false;
>  	/*
>  	 * Don't unmap buffer back, it will get reused
>  	 * by next bfdopen call
>  	 */
> +	pr_debug("BUF %p >\n", xb->mem);
> +	list_add(&xb->buf->l, &bufs);
> +	xb->buf = NULL;
> +	xb->mem = NULL;
> +	xb->pos = NULL;
>  }
>  
>  int bfdopen(struct bfd *f)
> diff --git a/include/bfd.h b/include/bfd.h
> index cea6d3a..dbaea16 100644
> --- a/include/bfd.h
> +++ b/include/bfd.h
> @@ -1,9 +1,11 @@
>  #ifndef __CR_BFD_H__
>  #define __CR_BFD_H__
> +struct bfd_buf;
>  struct xbuf {
>  	char *mem;		/* buffer */
>  	char *pos;		/* position we see bytes at */
>  	unsigned int bleft;	/* bytes left after b->pos */
> +	struct bfd_buf *buf;
>  };
>  
>  struct bfd {
> -- 
> 1.8.4.2
> 
> 


More information about the CRIU mailing list