Commit 5eb39aad authored by Pavel Emelyanov's avatar Pavel Emelyanov

bfd: Multiple buffers management (v2)

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: 's avatarPavel Emelyanov <xemul@parallels.com>
Acked-by: 's avatarAndrew Vagin <avagin@parallels.com>
parent 1a2e6cbd
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include "log.h" #include "log.h"
#include "bfd.h" #include "bfd.h"
#include "list.h"
#include "xmalloc.h"
#include "asm-generic/page.h" #include "asm-generic/page.h"
/* /*
...@@ -15,43 +17,70 @@ ...@@ -15,43 +17,70 @@
*/ */
#define BUFSIZE (PAGE_SIZE) #define BUFSIZE (PAGE_SIZE)
/* struct bfd_buf {
* XXX currently CRIU doesn't open several files char *mem;
* at once, so we can have just one buffer. struct list_head l;
*/ };
static char *buf;
static bool buf_busy; static LIST_HEAD(bufs);
#define BUFBATCH (16)
static int buf_get(struct xbuf *xb) static int buf_get(struct xbuf *xb)
{ {
if (buf_busy) { struct bfd_buf *b;
pr_err("bfd: Buffer busy\n");
return -1;
}
if (!buf) { if (list_empty(&bufs)) {
buf = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE, void *mem;
int i;
pr_debug("BUF++\n");
mem = mmap(NULL, BUFBATCH * BUFSIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, 0, 0); MAP_PRIVATE | MAP_ANON, 0, 0);
if (buf == MAP_FAILED) { if (mem == MAP_FAILED) {
pr_perror("bfd: No buf"); pr_perror("bfd: No buf");
return -1; 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;
} }
buf_busy = true; b->mem = mem + i * BUFSIZE;
xb->mem = buf; list_add_tail(&b->l, &bufs);
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->bleft = 0;
xb->buf = b;
pr_debug("BUF %p <\n", xb->mem);
return 0; return 0;
} }
static void buf_put(struct xbuf *xb) static void buf_put(struct xbuf *xb)
{ {
buf_busy = false;
/* /*
* Don't unmap buffer back, it will get reused * Don't unmap buffer back, it will get reused
* by next bfdopen call * 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) int bfdopen(struct bfd *f)
......
#ifndef __CR_BFD_H__ #ifndef __CR_BFD_H__
#define __CR_BFD_H__ #define __CR_BFD_H__
struct bfd_buf;
struct xbuf { struct xbuf {
char *mem; /* buffer */ char *mem; /* buffer */
char *pos; /* position we see bytes at */ char *pos; /* position we see bytes at */
unsigned int bleft; /* bytes left after b->pos */ unsigned int bleft; /* bytes left after b->pos */
struct bfd_buf *buf;
}; };
struct bfd { struct bfd {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment