[CRIU] [PATCH 11/15] bfd: Multiple buffers management (v2)
Pavel Emelyanov
xemul at parallels.com
Mon Sep 29 03:39:35 PDT 2014
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
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