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 @@
#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)
......
#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 {
......
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