bfd: serialize buffer pool access for parallel restore

Parallel memfd restore opens page images from multiple pthread workers
later in this series. Those paths can use bfd helpers, whose global
buffer pool was previously single-threaded.

Protect the shared buffer list around allocation, return, and buffer
extension paths. Add pthread linkage for the new restore-time pthread
users.

Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: Codex:gpt-5
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
This commit is contained in:
Dan Feigin 2026-04-26 14:22:38 +03:00 committed by Andrei Vagin
parent 8992fdb06a
commit 4b88445437
2 changed files with 12 additions and 1 deletions

View file

@ -27,7 +27,7 @@ REQ-DEB-PKG-TEST-NAMES += libaio-dev
REQ-RPM-PKG-TEST-NAMES += $(PYTHON)-PyYAML
export LIBS += -lprotobuf-c -ldl -lnl-3 -lsoccr -Lsoccr/ -lnet -luuid
export LIBS += -lprotobuf-c -ldl -lnl-3 -lsoccr -Lsoccr/ -lnet -luuid -lpthread
check-packages-failed:
$(warning Can not find some of the required libraries)

View file

@ -6,6 +6,7 @@
#include <fcntl.h>
#include <sys/uio.h>
#include <errno.h>
#include <pthread.h>
#include "int.h"
#include "log.h"
@ -33,6 +34,7 @@ struct bfd_buf {
};
static LIST_HEAD(bufs);
static pthread_mutex_t bufs_lock = PTHREAD_MUTEX_INITIALIZER;
#define BUFBATCH (16)
@ -40,12 +42,15 @@ static int buf_get(struct xbuf *xb)
{
struct bfd_buf *b;
pthread_mutex_lock(&bufs_lock);
if (list_empty(&bufs)) {
void *mem;
int i;
mem = mmap(NULL, BUFBATCH * BUFSIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
if (mem == MAP_FAILED) {
pthread_mutex_unlock(&bufs_lock);
pr_perror("No buf");
return -1;
}
@ -54,6 +59,7 @@ static int buf_get(struct xbuf *xb)
b = xmalloc(sizeof(*b));
if (!b) {
if (i == 0) {
pthread_mutex_unlock(&bufs_lock);
pr_err("No buffer for bfd\n");
return -1;
}
@ -75,6 +81,7 @@ static int buf_get(struct xbuf *xb)
xb->bsize = BUFSIZE;
xb->sz = 0;
xb->buf = b;
pthread_mutex_unlock(&bufs_lock);
return 0;
}
@ -85,7 +92,9 @@ static void buf_put(struct xbuf *xb)
* Don't unmap standard buffer back, it will get reused
* by next bfdopen call
*/
pthread_mutex_lock(&bufs_lock);
list_add(&xb->buf->l, &bufs);
pthread_mutex_unlock(&bufs_lock);
} else {
/* This buffer was dynamically extended, unmap it */
munmap(xb->mem, xb->bsize);
@ -199,7 +208,9 @@ static int bextend(struct bfd *f)
return -1;
}
memcpy(newbuf, b->mem, b->sz);
pthread_mutex_lock(&bufs_lock);
list_add(&b->buf->l, &bufs);
pthread_mutex_unlock(&bufs_lock);
b->buf = NULL;
} else {
newbuf = mremap(b->mem, b->bsize, newsize, MREMAP_MAYMOVE);