mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-22 22:03:43 +03:00
Merge pull request #16982 from yuwata/socket-buffer-size
Fixes for socket buffer size
This commit is contained in:
commit
39c4e2c1a1
@ -617,40 +617,62 @@ bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b
|
||||
return false;
|
||||
}
|
||||
|
||||
int fd_inc_sndbuf(int fd, size_t n) {
|
||||
int fd_set_sndbuf(int fd, size_t n, bool increase) {
|
||||
int r, value;
|
||||
socklen_t l = sizeof(value);
|
||||
|
||||
if (n > INT_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
|
||||
if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
|
||||
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
|
||||
return 0;
|
||||
|
||||
/* If we have the privileges we will ignore the kernel limit. */
|
||||
/* First, try to set the buffer size with SO_SNDBUF. */
|
||||
r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n) < 0) {
|
||||
r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
/* SO_SNDBUF above may set to the kernel limit, instead of the requested size.
|
||||
* So, we need to check the actual buffer size here. */
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
|
||||
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
|
||||
return 1;
|
||||
|
||||
/* If we have the privileges we will ignore the kernel limit. */
|
||||
r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fd_inc_rcvbuf(int fd, size_t n) {
|
||||
int fd_set_rcvbuf(int fd, size_t n, bool increase) {
|
||||
int r, value;
|
||||
socklen_t l = sizeof(value);
|
||||
|
||||
if (n > INT_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
|
||||
if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
|
||||
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
|
||||
return 0;
|
||||
|
||||
/* If we have the privileges we will ignore the kernel limit. */
|
||||
/* First, try to set the buffer size with SO_RCVBUF. */
|
||||
r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n) < 0) {
|
||||
r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
/* SO_RCVBUF above may set to the kernel limit, instead of the requested size.
|
||||
* So, we need to check the actual buffer size here. */
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
|
||||
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
|
||||
return 1;
|
||||
|
||||
/* If we have the privileges we will ignore the kernel limit. */
|
||||
r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -118,8 +118,14 @@ int netlink_family_from_string(const char *s) _pure_;
|
||||
|
||||
bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b);
|
||||
|
||||
int fd_inc_sndbuf(int fd, size_t n);
|
||||
int fd_inc_rcvbuf(int fd, size_t n);
|
||||
int fd_set_sndbuf(int fd, size_t n, bool increase);
|
||||
static inline int fd_inc_sndbuf(int fd, size_t n) {
|
||||
return fd_set_sndbuf(fd, n, true);
|
||||
}
|
||||
int fd_set_rcvbuf(int fd, size_t n, bool increase);
|
||||
static inline int fd_inc_rcvbuf(int fd, size_t n) {
|
||||
return fd_set_rcvbuf(fd, n, true);
|
||||
}
|
||||
|
||||
int ip_tos_to_string_alloc(int i, char **s);
|
||||
int ip_tos_from_string(const char *s);
|
||||
|
@ -1058,20 +1058,15 @@ static void socket_apply_socket_options(Socket *s, int fd) {
|
||||
}
|
||||
|
||||
if (s->receive_buffer > 0) {
|
||||
/* We first try with SO_RCVBUFFORCE, in case we have the perms for that */
|
||||
if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, s->receive_buffer) < 0) {
|
||||
r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, s->receive_buffer);
|
||||
if (r < 0)
|
||||
log_unit_warning_errno(UNIT(s), r, "SO_RCVBUF failed: %m");
|
||||
}
|
||||
r = fd_set_rcvbuf(fd, s->receive_buffer, false);
|
||||
if (r < 0)
|
||||
log_unit_warning_errno(UNIT(s), r, "SO_RCVBUF/SO_RCVBUFFORCE failed: %m");
|
||||
}
|
||||
|
||||
if (s->send_buffer > 0) {
|
||||
if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, s->send_buffer) < 0) {
|
||||
r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, s->send_buffer);
|
||||
if (r < 0)
|
||||
log_unit_warning_errno(UNIT(s), r, "SO_SNDBUF failed: %m");
|
||||
}
|
||||
r = fd_set_sndbuf(fd, s->receive_buffer, false);
|
||||
if (r < 0)
|
||||
log_unit_warning_errno(UNIT(s), r, "SO_SNDBUF/SO_SNDBUFFORCE failed: %m");
|
||||
}
|
||||
|
||||
if (s->mark >= 0) {
|
||||
|
@ -91,18 +91,9 @@ int device_monitor_allow_unicast_sender(sd_device_monitor *m, sd_device_monitor
|
||||
}
|
||||
|
||||
_public_ int sd_device_monitor_set_receive_buffer_size(sd_device_monitor *m, size_t size) {
|
||||
int r, n = (int) size;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return((size_t) n == size, -EINVAL);
|
||||
|
||||
if (setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUFFORCE, n) < 0) {
|
||||
r = setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUF, n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return fd_set_rcvbuf(m->sock, size, false);
|
||||
}
|
||||
|
||||
int device_monitor_disconnect(sd_device_monitor *m) {
|
||||
|
@ -36,11 +36,11 @@
|
||||
#include "path-util.h"
|
||||
#include "set.h"
|
||||
#include "signal-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "strv.h"
|
||||
#include "sysctl-util.h"
|
||||
#include "tmpfile-util.h"
|
||||
#include "udev-util.h"
|
||||
#include "virt.h"
|
||||
|
||||
/* use 128 MB for receive socket kernel queue. */
|
||||
#define RCVBUF_SIZE (128*1024*1024)
|
||||
@ -261,16 +261,19 @@ static int manager_udev_process_link(sd_device_monitor *monitor, sd_device *devi
|
||||
static int manager_connect_udev(Manager *m) {
|
||||
int r;
|
||||
|
||||
/* udev does not initialize devices inside containers,
|
||||
* so we rely on them being already initialized before
|
||||
* entering the container */
|
||||
if (detect_container() > 0)
|
||||
/* udev does not initialize devices inside containers, so we rely on them being already
|
||||
* initialized before entering the container. */
|
||||
if (path_is_read_only_fs("/sys") > 0)
|
||||
return 0;
|
||||
|
||||
r = sd_device_monitor_new(&m->device_monitor);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to initialize device monitor: %m");
|
||||
|
||||
r = sd_device_monitor_set_receive_buffer_size(m->device_monitor, RCVBUF_SIZE);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to increase buffer size for device monitor, ignoring: %m");
|
||||
|
||||
r = sd_device_monitor_filter_add_match_subsystem_devtype(m->device_monitor, "net", NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not add device monitor filter: %m");
|
||||
@ -1347,7 +1350,7 @@ static int manager_connect_genl(Manager *m) {
|
||||
|
||||
r = sd_netlink_inc_rcvbuf(m->genl, RCVBUF_SIZE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
log_warning_errno(r, "Failed to increase receive buffer size for general netlink socket, ignoring: %m");
|
||||
|
||||
r = sd_netlink_attach_event(m->genl, m->event, 0);
|
||||
if (r < 0)
|
||||
@ -1369,9 +1372,14 @@ static int manager_connect_rtnl(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_inc_rcvbuf(m->rtnl, RCVBUF_SIZE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
/* Bump receiver buffer, but only if we are not called via socket activation, as in that
|
||||
* case systemd sets the receive buffer size for us, and the value in the .socket unit
|
||||
* should take full effect. */
|
||||
if (fd < 0) {
|
||||
r = sd_netlink_inc_rcvbuf(m->rtnl, RCVBUF_SIZE);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to increase receive buffer size for rtnl socket, ignoring: %m");
|
||||
}
|
||||
|
||||
r = sd_netlink_attach_event(m->rtnl, m->event, 0);
|
||||
if (r < 0)
|
||||
|
@ -1686,8 +1686,11 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
|
||||
/* Bump receiver buffer, but only if we are not called via socket activation, as in that
|
||||
* case systemd sets the receive buffer size for us, and the value in the .socket unit
|
||||
* should take full effect. */
|
||||
if (fd_uevent < 0)
|
||||
(void) sd_device_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024);
|
||||
if (fd_uevent < 0) {
|
||||
r = sd_device_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to set receive buffer size for device monitor, ignoring: %m");
|
||||
}
|
||||
|
||||
r = device_monitor_enable_receiving(manager->monitor);
|
||||
if (r < 0)
|
||||
|
Loading…
x
Reference in New Issue
Block a user