[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