]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
socket: parse message queue size as IEC size
authordongshengyuan <545258830@qq.com>
Fri, 31 Jul 2026 07:52:43 +0000 (15:52 +0800)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 2 Aug 2026 10:17:51 +0000 (19:17 +0900)
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.

TODO.md
man/systemd.socket.xml
src/core/dbus-socket.c
src/core/load-fragment-gperf.gperf.in
src/shared/bus-unit-util.c
src/shared/conf-parser.c
src/shared/conf-parser.h
src/test/test-bus-unit-util.c
src/test/test-conf-parser.c

diff --git a/TODO.md b/TODO.md
index d0659553aee715508d0c4ffa1bd4475ccf433eb9..f39bc16ec2f6f7af485ea7b856fa994e09d131ee 100644 (file)
--- 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
index 6816b073b36524a8f16b7782a9b36f2868c59237..7baf439f34665709262bc139a7d2e657a1ace271 100644 (file)
       <varlistentry>
         <term><varname>MessageQueueMaxMessages=</varname>,
         <varname>MessageQueueMessageSize=</varname></term>
-        <listitem><para>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
+        <listitem><para>These two settings control the mq_maxmsg field or
+        the mq_msgsize field, respectively, when creating the message queue.
+        <varname>MessageQueueMaxMessages=</varname> takes an integer value.
+        <varname>MessageQueueMessageSize=</varname> 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
         <citerefentry project='die-net'><refentrytitle>mq_setattr</refentrytitle><manvolnum>3</manvolnum></citerefentry>
         for details.</para></listitem>
       </varlistentry>
index 26612015f05380db165a4318c1ea259f69343297..9b347e3c55e56dda4f02923afe327c7bc92fde51 100644 (file)
@@ -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);
index aa95bd49920011c7e79f77321e47d0bf94394b5f..57a56f299a24d44c94c3e1e661708bafc46ffe70 100644 (file)
@@ -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
index 48a48f71b21707e0e197f96223fd24d7ae49166e..9ee8a0ad04a264f507eb740341dbe72125e3f7cf 100644 (file)
@@ -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                       },
index f9f113eadc0258875d037a14c6bcdb77fe71cd4c..ffe888a4396b759c522325918d56895883541836 100644 (file)
@@ -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,
index 0d1324b67d8a2462e51c51a2e7fff0017a7cb84d..c1fa64b339e9432e28d6b267b8a5c85ecb753af2 100644 (file)
@@ -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);
index ae2cb19c9ce0a98a5b73e6537ee8791500f0d5af..8185d0269f1ab90fb351556bfe78898cbf2bcc3b 100644 (file)
@@ -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",
index 5cae59ce717b15a176298ffb2ea2d0faa9ddc592..c7747cee4ae644bb8b0dbd284b79d2f41963e241 100644 (file)
@@ -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);