From: dongshengyuan <545258830@qq.com> Date: Fri, 31 Jul 2026 07:52:43 +0000 (+0800) Subject: socket: parse message queue size as IEC size X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=78238fd7c9bcdc4272c4aa22930424a2febf6768;p=thirdparty%2Fsystemd.git socket: parse message queue size as IEC size Allow MessageQueueMessageSize= to accept IEC size suffixes in socket unit files. Support the same syntax for transient property assignments. Keep MessageQueueMaxMessages= as a plain message count. --- diff --git a/TODO.md b/TODO.md index d0659553aee..f39bc16ec2f 100644 --- a/TODO.md +++ b/TODO.md @@ -1775,8 +1775,6 @@ SPDX-License-Identifier: LGPL-2.1-or-later - merge unit_kill_common() and unit_kill_context() -- MessageQueueMessageSize= (and suchlike) should use parse_iec_size(). - - mount /tmp/ and /var/tmp with a uidmap applied that blocks out "nobody" user among other things such as dynamic uid ranges for containers and so on. That way no one can create files there with these uids and we enforce they are only diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 6816b073b36..7baf439f346 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -742,10 +742,12 @@ MessageQueueMaxMessages=, MessageQueueMessageSize= - These two settings take integer values and - control the mq_maxmsg field or the mq_msgsize field, - respectively, when creating the message queue. Note that - either none or both of these variables need to be set. See + These two settings control the mq_maxmsg field or + the mq_msgsize field, respectively, when creating the message queue. + MessageQueueMaxMessages= takes an integer value. + MessageQueueMessageSize= takes a size in bytes, and + the usual suffixes K, M, G are supported and understood to the base of + 1024. Note that either none or both of these variables need to be set. See mq_setattr3 for details. diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index 26612015f05..9b347e3c55e 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -162,6 +162,10 @@ static bool check_size_t_truncation(uint64_t t) { return (size_t) t == t; } +static bool check_long_truncation(int64_t t) { + return (int64_t) (long) t == t; +} + static const char* socket_protocol_to_string(int32_t i) { if (i == IPPROTO_IP) return ""; @@ -173,7 +177,7 @@ static const char* socket_protocol_to_string(int32_t i) { } static BUS_DEFINE_SET_TRANSIENT(int, "i", int32_t, int, "%" PRIi32); -static BUS_DEFINE_SET_TRANSIENT(message_queue, "x", int64_t, long, "%" PRIi64); +static BUS_DEFINE_SET_TRANSIENT_IS_VALID(message_queue, "x", int64_t, long, "%" PRIi64, check_long_truncation); static BUS_DEFINE_SET_TRANSIENT_IS_VALID(size_t_check_truncation, "t", uint64_t, size_t, "%" PRIu64, check_size_t_truncation); static BUS_DEFINE_SET_TRANSIENT_PARSE(bind_ipv6_only, SocketAddressBindIPv6Only, socket_address_bind_ipv6_only_or_bool_from_string); static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(fdname, fdname_is_valid); diff --git a/src/core/load-fragment-gperf.gperf.in b/src/core/load-fragment-gperf.gperf.in index aa95bd49920..57a56f299a2 100644 --- a/src/core/load-fragment-gperf.gperf.in +++ b/src/core/load-fragment-gperf.gperf.in @@ -549,7 +549,7 @@ Socket.Timestamping, config_parse_socket_timestamping, Socket.TCPCongestion, config_parse_string, 0, offsetof(Socket, tcp_congestion) Socket.ReusePort, config_parse_bool, 0, offsetof(Socket, reuse_port) Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg) -Socket.MessageQueueMessageSize, config_parse_long, 0, offsetof(Socket, mq_msgsize) +Socket.MessageQueueMessageSize, config_parse_iec_size_long, 0, offsetof(Socket, mq_msgsize) Socket.RemoveOnStop, config_parse_bool, 0, offsetof(Socket, remove_on_stop) Socket.Symlinks, config_parse_unit_path_strv_printf, 0, offsetof(Socket, symlinks) Socket.FileDescriptorName, config_parse_fdname, 0, 0 diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index 48a48f71b21..9ee8a0ad04a 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -347,6 +347,23 @@ static int bus_append_parse_size(sd_bus_message *m, const char *field, const cha return 1; } +static int bus_append_parse_size_i64(sd_bus_message *m, const char *field, const char *eq) { + uint64_t v; + int r; + + r = parse_size(eq, /* base= */ 1024, &v); + if (r < 0) + return parse_log_error(r, field, eq); + if (v > INT64_MAX) + return parse_log_error(SYNTHETIC_ERRNO(ERANGE), field, eq); + + r = sd_bus_message_append(m, "(sv)", field, "x", (int64_t) v); + if (r < 0) + return bus_log_create_error(r); + + return 1; +} + static int bus_append_parse_permyriad(sd_bus_message *m, const char *field, const char *eq) { int r; @@ -2811,7 +2828,6 @@ static const BusProperty socket_properties[] = { { "SocketMode", bus_append_parse_mode }, { "DirectoryMode", bus_append_parse_mode }, { "MessageQueueMaxMessages", bus_append_safe_atoi64 }, - { "MessageQueueMessageSize", bus_append_safe_atoi64 }, { "TimeoutSec", bus_append_parse_sec_rename }, { "KeepAliveTimeSec", bus_append_parse_sec_rename }, { "KeepAliveIntervalSec", bus_append_parse_sec_rename }, @@ -2822,6 +2838,7 @@ static const BusProperty socket_properties[] = { { "ReceiveBuffer", bus_append_parse_size }, { "SendBuffer", bus_append_parse_size }, { "PipeSize", bus_append_parse_size }, + { "MessageQueueMessageSize", bus_append_parse_size_i64 }, { "ExecStartPre", bus_append_exec_command }, { "ExecStartPost", bus_append_exec_command }, { "ExecReload", bus_append_exec_command }, diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index f9f113eadc0..ffe888a4396 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -1001,6 +1001,36 @@ int config_parse_iec_size( return 1; } +int config_parse_iec_size_long( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + long *sz = ASSERT_PTR(data); + uint64_t v; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = parse_size(rvalue, 1024, &v); + if (r >= 0 && v > LONG_MAX) + r = -ERANGE; + if (r < 0) + return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue); + + *sz = (long) v; + return 1; +} + int config_parse_si_uint64( const char *unit, const char *filename, diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h index 0d1324b67d8..c1fa64b339e 100644 --- a/src/shared/conf-parser.h +++ b/src/shared/conf-parser.h @@ -237,6 +237,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_int32); CONFIG_PARSER_PROTOTYPE(config_parse_uint64); CONFIG_PARSER_PROTOTYPE(config_parse_double); CONFIG_PARSER_PROTOTYPE(config_parse_iec_size); +CONFIG_PARSER_PROTOTYPE(config_parse_iec_size_long); CONFIG_PARSER_PROTOTYPE(config_parse_si_uint64); CONFIG_PARSER_PROTOTYPE(config_parse_iec_uint64); CONFIG_PARSER_PROTOTYPE(config_parse_iec_uint64_infinity); diff --git a/src/test/test-bus-unit-util.c b/src/test/test-bus-unit-util.c index ae2cb19c9ce..8185d0269f1 100644 --- a/src/test/test-bus-unit-util.c +++ b/src/test/test-bus-unit-util.c @@ -848,7 +848,6 @@ TEST(socket_properties) { /* 64-bit integer properties */ "MessageQueueMaxMessages=10", - "MessageQueueMessageSize=8192", /* Timespan properties */ "TimeoutSec=90s", @@ -871,6 +870,7 @@ TEST(socket_properties) { "ReceiveBuffer=512K", "SendBuffer=1.M", // TODO: should this accept multiple components? "PipeSize=512K", + "MessageQueueMessageSize=8K", /* Exec command properties */ "ExecStartPre=true", diff --git a/src/test/test-conf-parser.c b/src/test/test-conf-parser.c index 5cae59ce717..c7747cee4ae 100644 --- a/src/test/test-conf-parser.c +++ b/src/test/test-conf-parser.c @@ -41,6 +41,14 @@ static void test_config_parse_iec_size_one(const char *rvalue, size_t expected) ASSERT_EQ(expected, iec_size); } +static void test_config_parse_iec_size_long_one(const char *rvalue, long expected) { + long iec_size = 0; + + ASSERT_OK(config_parse_iec_size_long( + "unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &iec_size, NULL)); + ASSERT_EQ(expected, iec_size); +} + static void test_config_parse_si_uint64_one(const char *rvalue, uint64_t expected) { uint64_t si_uint64 = 0; @@ -135,6 +143,19 @@ TEST(config_parse_iec_size) { test_config_parse_iec_size_one("garbage", 0); } +TEST(config_parse_iec_size_long) { + test_config_parse_iec_size_long_one("1024", 1024); + test_config_parse_iec_size_long_one("2K", 2048); + test_config_parse_iec_size_long_one("10M", 10 * 1024 * 1024); + test_config_parse_iec_size_long_one("1G", 1L * 1024 * 1024 * 1024); + test_config_parse_iec_size_long_one("0G", 0); + test_config_parse_iec_size_long_one("0", 0); + + test_config_parse_iec_size_long_one("-982", 0); + test_config_parse_iec_size_long_one("49874444198739873000000G", 0); + test_config_parse_iec_size_long_one("garbage", 0); +} + TEST(config_parse_si_uint64) { test_config_parse_si_uint64_one("1024", 1024); test_config_parse_si_uint64_one("2K", 2000);