Skip to content

Commit 069f5e6

Browse files
committed
bus: implement synchronous message calls via kernel ioctl
1 parent 607553f commit 069f5e6

File tree

3 files changed

+65
-28
lines changed

3 files changed

+65
-28
lines changed

src/libsystemd/sd-bus/bus-kernel.c

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
206206
assert(m);
207207
assert(m->sealed);
208208

209+
/* We put this together only once, if this message is reused
210+
* we reuse the earlier-built version */
209211
if (m->kdbus)
210212
return 0;
211213

@@ -722,7 +724,26 @@ int bus_kernel_connect(sd_bus *b) {
722724
return bus_kernel_take_fd(b);
723725
}
724726

725-
int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
727+
static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
728+
uint64_t off;
729+
struct kdbus_item *d;
730+
731+
assert(bus);
732+
assert(k);
733+
734+
off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
735+
ioctl(bus->input_fd, KDBUS_CMD_FREE, &off);
736+
737+
KDBUS_ITEM_FOREACH(d, k, items) {
738+
739+
if (d->type == KDBUS_ITEM_FDS)
740+
close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
741+
else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
742+
close_nointr_nofail(d->memfd.fd);
743+
}
744+
}
745+
746+
int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call) {
726747
int r;
727748

728749
assert(bus);
@@ -738,6 +759,14 @@ int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
738759
if (r < 0)
739760
return r;
740761

762+
/* If this is a synchronous method call, then let's tell the
763+
* kernel, so that it can pass CPU time/scheduling to the
764+
* destination for the time, if it wants to. If we
765+
* synchronously wait for the result anyway, we won't need CPU
766+
* anyway. */
767+
if (hint_sync_call)
768+
m->kdbus->flags |= KDBUS_MSG_FLAGS_EXPECT_REPLY|KDBUS_MSG_FLAGS_SYNC_REPLY;
769+
741770
r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
742771
if (r < 0) {
743772
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
@@ -785,29 +814,31 @@ int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
785814

786815
bus->rqueue[bus->rqueue_size++] = reply;
787816

788-
return 0;
789-
}
817+
} else if (hint_sync_call) {
818+
struct kdbus_msg *k;
790819

791-
return 1;
792-
}
820+
k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + m->kdbus->offset_reply);
821+
assert(k);
793822

794-
static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
795-
uint64_t off;
796-
struct kdbus_item *d;
797-
798-
assert(bus);
799-
assert(k);
823+
if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
800824

801-
off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
802-
ioctl(bus->input_fd, KDBUS_CMD_FREE, &off);
803-
804-
KDBUS_ITEM_FOREACH(d, k, items) {
825+
r = bus_kernel_make_message(bus, k);
826+
if (r < 0) {
827+
close_kdbus_msg(bus, k);
805828

806-
if (d->type == KDBUS_ITEM_FDS)
807-
close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
808-
else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
809-
close_nointr_nofail(d->memfd.fd);
829+
/* Anybody can send us invalid messages, let's just drop them. */
830+
if (r == -EBADMSG || r == -EPROTOTYPE)
831+
log_debug("Ignoring invalid message: %s", strerror(-r));
832+
else
833+
return r;
834+
}
835+
} else {
836+
log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
837+
close_kdbus_msg(bus, k);
838+
}
810839
}
840+
841+
return 1;
811842
}
812843

813844
static int push_name_owner_changed(sd_bus *bus, const char *name, const char *old_owner, const char *new_owner) {
@@ -964,8 +995,8 @@ int bus_kernel_read_message(sd_bus *bus) {
964995

965996
return -errno;
966997
}
967-
k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + recv.offset);
968998

999+
k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + recv.offset);
9691000
if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
9701001
r = bus_kernel_make_message(bus, k);
9711002

@@ -977,8 +1008,10 @@ int bus_kernel_read_message(sd_bus *bus) {
9771008

9781009
} else if (k->payload_type == KDBUS_PAYLOAD_KERNEL)
9791010
r = bus_kernel_translate_message(bus, k);
980-
else
1011+
else {
1012+
log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
9811013
r = 0;
1014+
}
9821015

9831016
if (r <= 0)
9841017
close_kdbus_msg(bus, k);

src/libsystemd/sd-bus/bus-kernel.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ struct memfd_cache {
6060
int bus_kernel_connect(sd_bus *b);
6161
int bus_kernel_take_fd(sd_bus *b);
6262

63-
int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m);
63+
int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call);
6464
int bus_kernel_read_message(sd_bus *bus);
6565

6666
int bus_kernel_create_bus(const char *name, bool world, char **s);

src/libsystemd/sd-bus/sd-bus.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,14 +1371,14 @@ int bus_seal_synthetic_message(sd_bus *b, sd_bus_message *m) {
13711371
return bus_message_seal(m, 0xFFFFFFFFULL, 0);
13721372
}
13731373

1374-
static int bus_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
1374+
static int bus_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call, size_t *idx) {
13751375
int r;
13761376

13771377
assert(bus);
13781378
assert(m);
13791379

13801380
if (bus->is_kernel)
1381-
r = bus_kernel_write_message(bus, m);
1381+
r = bus_kernel_write_message(bus, m, hint_sync_call);
13821382
else
13831383
r = bus_socket_write_message(bus, m, idx);
13841384

@@ -1408,7 +1408,7 @@ static int dispatch_wqueue(sd_bus *bus) {
14081408

14091409
while (bus->wqueue_size > 0) {
14101410

1411-
r = bus_write_message(bus, bus->wqueue[0], &bus->windex);
1411+
r = bus_write_message(bus, bus->wqueue[0], false, &bus->windex);
14121412
if (r < 0)
14131413
return r;
14141414
else if (r == 0)
@@ -1486,7 +1486,7 @@ static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) {
14861486
}
14871487
}
14881488

1489-
_public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) {
1489+
static int bus_send_internal(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie, bool hint_sync_call) {
14901490
_cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
14911491
int r;
14921492

@@ -1526,7 +1526,7 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) {
15261526
if ((bus->state == BUS_RUNNING || bus->state == BUS_HELLO) && bus->wqueue_size <= 0) {
15271527
size_t idx = 0;
15281528

1529-
r = bus_write_message(bus, m, &idx);
1529+
r = bus_write_message(bus, m, hint_sync_call, &idx);
15301530
if (r < 0) {
15311531
if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
15321532
bus_enter_closing(bus);
@@ -1562,6 +1562,10 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) {
15621562
return 1;
15631563
}
15641564

1565+
_public_ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *cookie) {
1566+
return bus_send_internal(bus, m, cookie, false);
1567+
}
1568+
15651569
_public_ int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *cookie) {
15661570
int r;
15671571

@@ -1755,7 +1759,7 @@ _public_ int sd_bus_call(
17551759
if (r < 0)
17561760
return r;
17571761

1758-
r = sd_bus_send(bus, m, &cookie);
1762+
r = bus_send_internal(bus, m, &cookie, true);
17591763
if (r < 0)
17601764
return r;
17611765

0 commit comments

Comments
 (0)