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.
This commit is contained in:
dongshengyuan
2026-07-31 15:52:43 +08:00
committed by Yu Watanabe
parent 3bb3c54f3d
commit 78238fd7c9
9 changed files with 83 additions and 10 deletions

View File

@@ -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

View File

@@ -742,10 +742,12 @@
<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>

View 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);

View 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

View 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 },

View 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,

View 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);

View 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",

View 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);