bus: calculate iovec for messages only when we need it
This commit is contained in:
@@ -302,7 +302,6 @@ int bus_message_from_malloc(
|
||||
m->n_iovec = 1;
|
||||
m->iovec[0].iov_base = buffer;
|
||||
m->iovec[0].iov_len = length;
|
||||
m->size = length;
|
||||
|
||||
r = message_parse_fields(m);
|
||||
if (r < 0)
|
||||
@@ -2794,42 +2793,6 @@ static int message_parse_fields(sd_bus_message *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setup_iovec(sd_bus_message *m) {
|
||||
assert(m);
|
||||
assert(m->sealed);
|
||||
|
||||
m->n_iovec = 0;
|
||||
m->size = 0;
|
||||
|
||||
m->iovec[m->n_iovec].iov_base = m->header;
|
||||
m->iovec[m->n_iovec].iov_len = sizeof(*m->header);
|
||||
m->size += m->iovec[m->n_iovec].iov_len;
|
||||
m->n_iovec++;
|
||||
|
||||
if (m->fields) {
|
||||
m->iovec[m->n_iovec].iov_base = m->fields;
|
||||
m->iovec[m->n_iovec].iov_len = m->header->fields_size;
|
||||
m->size += m->iovec[m->n_iovec].iov_len;
|
||||
m->n_iovec++;
|
||||
|
||||
if (m->header->fields_size % 8 != 0) {
|
||||
static const uint8_t padding[7] = { 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
m->iovec[m->n_iovec].iov_base = (void*) padding;
|
||||
m->iovec[m->n_iovec].iov_len = 8 - m->header->fields_size % 8;
|
||||
m->size += m->iovec[m->n_iovec].iov_len;
|
||||
m->n_iovec++;
|
||||
}
|
||||
}
|
||||
|
||||
if (m->body) {
|
||||
m->iovec[m->n_iovec].iov_base = m->body;
|
||||
m->iovec[m->n_iovec].iov_len = m->header->body_size;
|
||||
m->size += m->iovec[m->n_iovec].iov_len;
|
||||
m->n_iovec++;
|
||||
}
|
||||
}
|
||||
|
||||
int bus_message_seal(sd_bus_message *m, uint64_t serial) {
|
||||
int r;
|
||||
|
||||
@@ -2857,8 +2820,6 @@ int bus_message_seal(sd_bus_message *m, uint64_t serial) {
|
||||
m->header->serial = serial;
|
||||
m->sealed = true;
|
||||
|
||||
setup_iovec(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3074,22 +3035,31 @@ int bus_message_dump(sd_bus_message *m) {
|
||||
|
||||
int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
|
||||
size_t total;
|
||||
unsigned i;
|
||||
void *p, *e;
|
||||
|
||||
assert(m);
|
||||
assert(buffer);
|
||||
assert(sz);
|
||||
|
||||
for (i = 0, total = 0; i < m->n_iovec; i++)
|
||||
total += m->iovec[i].iov_len;
|
||||
total = bus_message_size(m);
|
||||
|
||||
p = malloc(total);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0, e = p; i < m->n_iovec; i++)
|
||||
e = mempcpy(e, m->iovec[i].iov_base, m->iovec[i].iov_len);
|
||||
e = mempcpy(p, m->header, sizeof(*m->header));
|
||||
|
||||
if (m->fields) {
|
||||
e = mempcpy(e, m->fields, m->header->fields_size);
|
||||
|
||||
if (m->header->fields_size % 8 != 0)
|
||||
e = mempset(e, 0, 8 - (m->header->fields_size % 8));
|
||||
}
|
||||
|
||||
if (m->body)
|
||||
e = mempcpy(e, m->body, m->header->body_size);
|
||||
|
||||
assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
|
||||
|
||||
*buffer = p;
|
||||
*sz = total;
|
||||
@@ -3162,3 +3132,13 @@ const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
size_t bus_message_size(sd_bus_message *m) {
|
||||
assert(m);
|
||||
assert(m->sealed);
|
||||
|
||||
return
|
||||
sizeof(*m->header) +
|
||||
ALIGN8(m->header->fields_size) +
|
||||
m->header->body_size;
|
||||
}
|
||||
|
||||
@@ -92,7 +92,6 @@ struct sd_bus_message {
|
||||
|
||||
struct iovec iovec[4];
|
||||
unsigned n_iovec;
|
||||
size_t size;
|
||||
|
||||
char *peeked_signature;
|
||||
};
|
||||
@@ -146,3 +145,5 @@ int bus_message_from_malloc(
|
||||
const char* bus_message_get_arg(sd_bus_message *m, unsigned i);
|
||||
|
||||
int bus_message_append_ap(sd_bus_message *m, const char *types, va_list ap);
|
||||
|
||||
size_t bus_message_size(sd_bus_message *m);
|
||||
|
||||
@@ -58,6 +58,39 @@ static void iovec_advance(struct iovec iov[], unsigned *idx, size_t size) {
|
||||
}
|
||||
}
|
||||
|
||||
static void append_iovec(sd_bus_message *m, const void *p, size_t sz) {
|
||||
assert(m);
|
||||
assert(p);
|
||||
assert(sz > 0);
|
||||
|
||||
m->iovec[m->n_iovec].iov_base = (void*) p;
|
||||
m->iovec[m->n_iovec].iov_len = sz;
|
||||
m->n_iovec++;
|
||||
}
|
||||
|
||||
static void bus_message_setup_iovec(sd_bus_message *m) {
|
||||
assert(m);
|
||||
assert(m->sealed);
|
||||
|
||||
if (m->n_iovec > 0)
|
||||
return;
|
||||
|
||||
append_iovec(m, m->header, sizeof(*m->header));
|
||||
|
||||
if (m->fields) {
|
||||
append_iovec(m, m->fields, m->header->fields_size);
|
||||
|
||||
if (m->header->fields_size % 8 != 0) {
|
||||
static const uint8_t padding[7] = {};
|
||||
|
||||
append_iovec(m, padding, 8 - (m->header->fields_size % 8));
|
||||
}
|
||||
}
|
||||
|
||||
if (m->body)
|
||||
append_iovec(m, m->body, m->header->body_size);
|
||||
}
|
||||
|
||||
bool bus_socket_auth_needs_write(sd_bus *b) {
|
||||
|
||||
unsigned i;
|
||||
@@ -729,9 +762,11 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
|
||||
assert(idx);
|
||||
assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
|
||||
|
||||
if (*idx >= m->size)
|
||||
if (*idx >= bus_message_size(m))
|
||||
return 0;
|
||||
|
||||
bus_message_setup_iovec(m);
|
||||
|
||||
n = m->n_iovec * sizeof(struct iovec);
|
||||
iov = alloca(n);
|
||||
memcpy(iov, m->iovec, n);
|
||||
|
||||
@@ -965,7 +965,7 @@ static int dispatch_wqueue(sd_bus *bus) {
|
||||
} else if (r == 0)
|
||||
/* Didn't do anything this time */
|
||||
return ret;
|
||||
else if (bus->windex >= bus->wqueue[0]->size) {
|
||||
else if (bus->windex >= bus_message_size(bus->wqueue[0])) {
|
||||
/* Fully written. Let's drop the entry from
|
||||
* the queue.
|
||||
*
|
||||
@@ -1066,7 +1066,7 @@ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) {
|
||||
if (r < 0) {
|
||||
sd_bus_close(bus);
|
||||
return r;
|
||||
} else if (idx < m->size) {
|
||||
} else if (idx < bus_message_size(m)) {
|
||||
/* Wasn't fully written. So let's remember how
|
||||
* much was written. Note that the first entry
|
||||
* of the wqueue array is always allocated so
|
||||
|
||||
Reference in New Issue
Block a user