diff options
author | Lennart Poettering <lennart@poettering.net> | 2013-12-18 18:46:23 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2013-12-18 19:04:14 +0100 |
commit | 8e959fbf3862172b53d200cda659795c3744fa78 (patch) | |
tree | af7f63d5b925d321ee2aac5afbbdf55af786e9eb /src/libsystemd-bus/bus-message.c | |
parent | e7d43b3cc30764138c90eaaf95d3d8f49e448890 (diff) |
bus: reduce calls to KDBUS_CMD_MEMFD_SIZE_SET ioctl
Instead of calling it for each buffer append, increase allocation
exponentially and set the real value only at the end, when sealing off
the memfd.
This should drastically reduce the number of times we invoke the
ioctl().
Diffstat (limited to 'src/libsystemd-bus/bus-message.c')
-rw-r--r-- | src/libsystemd-bus/bus-message.c | 54 |
1 files changed, 39 insertions, 15 deletions
diff --git a/src/libsystemd-bus/bus-message.c b/src/libsystemd-bus/bus-message.c index 1a461e62e0..d6888738e1 100644 --- a/src/libsystemd-bus/bus-message.c +++ b/src/libsystemd-bus/bus-message.c @@ -65,7 +65,7 @@ static void message_free_part(sd_bus_message *m, struct bus_body_part *part) { * can't be sealed yet. */ if (!part->sealed) - bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped); + bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated); else { if (part->mapped > 0) assert_se(munmap(part->data, part->mapped) == 0); @@ -1049,20 +1049,27 @@ static int part_make_space( return -ENOMEM; if (!part->data && part->memfd < 0) - part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped); + part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated); if (part->memfd >= 0) { - uint64_t u = sz; - r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &u); - if (r < 0) { - m->poisoned = true; - return -errno; + if (part->allocated == 0 || sz > part->allocated) { + uint64_t new_allocated; + + new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1); + r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &new_allocated); + if (r < 0) { + m->poisoned = true; + return -errno; + } + + part->allocated = new_allocated; } if (!part->data || sz > part->mapped) { - size_t psz = PAGE_ALIGN(sz > 0 ? sz : 1); + size_t psz; + psz = PAGE_ALIGN(sz > 0 ? sz : 1); if (part->mapped <= 0) n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0); else @@ -1079,14 +1086,20 @@ static int part_make_space( part->munmap_this = true; } else { - n = realloc(part->data, MAX(sz, 1u)); - if (!n) { - m->poisoned = true; - return -ENOMEM; - } + if (part->allocated == 0 || sz > part->allocated) { + size_t new_allocated; + + new_allocated = sz > 0 ? 2 * sz : 64; + n = realloc(part->data, new_allocated); + if (!n) { + m->poisoned = true; + return -ENOMEM; + } - part->data = n; - part->free_this = true; + part->data = n; + part->allocated = new_allocated; + part->free_this = true; + } } if (q) @@ -2757,8 +2770,19 @@ int bus_message_seal(sd_bus_message *m, uint64_t serial, usec_t timeout) { if (m->destination && m->bus && m->bus->use_memfd) { MESSAGE_FOREACH_PART(part, i, m) if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) { + uint64_t sz; + + /* Try to seal it if that makes + * sense. First, unmap our own map to + * make sure we don't keep it busy. */ bus_body_part_unmap(part); + /* Then, sync up real memfd size */ + sz = part->size; + if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &sz) < 0) + return -errno; + + /* Finally, try to seal */ if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0) part->sealed = true; } |