mem: add a PW_MEMBLOCK_FLAG_MAPPABLE flag and pass it around

This flags means that the fd can be mmaped without special handling. It
is the equivalent of the SPA_DATA_FLAG_MAPPABLE. Refuse to map memory
that is not mappable.

Make sure we make all allocated MemFd memory MAPPABLE by default. We can
then remove the stream and filter special handling for MemFd types and
just check the more generic MAPPABLE flag.

Make one exception when a client uploads MemFd buffer memory. We must
manually set the MAPPABLE flag for MemFd to make things backwards
compatible.
This commit is contained in:
Wim Taymans 2024-04-02 10:44:06 +02:00
parent 45984fef77
commit 2f8740dee8
12 changed files with 63 additions and 38 deletions

View file

@ -858,6 +858,8 @@ do_port_use_buffers(struct impl *impl,
{
uint32_t flags = PW_MEMBLOCK_FLAG_DONT_CLOSE;
if (d->flags & SPA_DATA_FLAG_MAPPABLE)
flags |= PW_MEMBLOCK_FLAG_MAPPABLE;
if (d->flags & SPA_DATA_FLAG_READABLE)
flags |= PW_MEMBLOCK_FLAG_READABLE;
if (d->flags & SPA_DATA_FLAG_WRITABLE)
@ -1084,16 +1086,27 @@ static int client_node_port_buffers(void *data,
for (j = 0; j < b->buffer.n_datas; j++) {
struct spa_chunk *oldchunk = oldbuf->datas[j].chunk;
struct spa_data *d = &newbuf->datas[j];
uint32_t flags = d->flags;
if (d->type == SPA_DATA_MemFd &&
!SPA_FLAG_IS_SET(flags, SPA_DATA_FLAG_MAPPABLE)) {
spa_log_debug(impl->log, "buffer:%d data:%d has non mappable MemFd, "
"fixing to ensure backwards compatibility.",
i, j);
flags |= SPA_DATA_FLAG_MAPPABLE;
}
/* overwrite everything except the chunk */
oldbuf->datas[j] = *d;
oldbuf->datas[j].flags = flags;
oldbuf->datas[j].chunk = oldchunk;
b->datas[j].type = d->type;
b->datas[j].flags = flags;
b->datas[j].fd = d->fd;
spa_log_debug(impl->log, " data %d type:%d fl:%08x fd:%d, offs:%d max:%d",
j, d->type, d->flags, (int) d->fd, d->mapoffset,
j, d->type, flags, (int) d->fd, d->mapoffset,
d->maxsize);
}
}
@ -1342,8 +1355,9 @@ static int add_area(struct impl *impl)
area = pw_mempool_alloc(impl->context_pool,
PW_MEMBLOCK_FLAG_READWRITE |
PW_MEMBLOCK_FLAG_MAP |
PW_MEMBLOCK_FLAG_SEAL,
PW_MEMBLOCK_FLAG_SEAL |
PW_MEMBLOCK_FLAG_MAPPABLE |
PW_MEMBLOCK_FLAG_MAP,
SPA_DATA_MemFd, size);
if (area == NULL)
return -errno;

View file

@ -701,14 +701,14 @@ client_node_port_use_buffers(void *_data,
d->type = bm->type;
d->data = NULL;
pw_log_debug(" data %d %u -> fd %d maxsize %d",
j, bm->id, bm->fd, d->maxsize);
pw_log_debug(" data %d %u -> fd %d maxsize %d flags:%08x",
j, bm->id, bm->fd, d->maxsize, d->flags);
} else if (d->type == SPA_DATA_MemPtr) {
int offs = SPA_PTR_TO_INT(d->data);
d->data = SPA_PTROFF(mm->ptr, offs, void);
d->fd = -1;
pw_log_debug(" data %d id:%u -> mem:%p offs:%d maxsize:%d",
j, bid->id, d->data, offs, d->maxsize);
pw_log_debug(" data %d id:%u -> mem:%p offs:%d maxsize:%d flags:%08x",
j, bid->id, d->data, offs, d->maxsize, d->flags);
} else {
pw_log_warn("unknown buffer data type %d", d->type);
}

View file

@ -191,8 +191,9 @@ pw_client_node0_transport_new(struct pw_context *context,
impl->mem = pw_mempool_alloc(pw_context_get_mempool(context),
PW_MEMBLOCK_FLAG_READWRITE |
PW_MEMBLOCK_FLAG_MAP |
PW_MEMBLOCK_FLAG_SEAL,
PW_MEMBLOCK_FLAG_SEAL |
PW_MEMBLOCK_FLAG_MAPPABLE |
PW_MEMBLOCK_FLAG_MAP,
SPA_DATA_MemFd, area_get_size(&area));
if (impl->mem == NULL) {
free(impl);