mirror of
https://github.com/systemd/systemd
synced 2025-10-04 11:14:45 +02:00
Compare commits
9 Commits
e5f8ce13bb
...
4b252eaa31
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4b252eaa31 | ||
![]() |
749c4c8ed1 | ||
![]() |
ffea01856f | ||
![]() |
c7209bcfe1 | ||
![]() |
4fa024683c | ||
![]() |
64a65bab59 | ||
![]() |
873446f2e4 | ||
![]() |
0fa7b50053 | ||
![]() |
81504017f4 |
@ -527,41 +527,22 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int controller_is_accessible(const char *controller) {
|
static int controller_is_v1_accessible(const char *root, const char *controller) {
|
||||||
int r;
|
const char *cpath, *dn;
|
||||||
|
|
||||||
assert(controller);
|
assert(controller);
|
||||||
|
|
||||||
/* Checks whether a specific controller is accessible,
|
|
||||||
* i.e. its hierarchy mounted. In the unified hierarchy all
|
|
||||||
* controllers are considered accessible, except for the named
|
|
||||||
* hierarchies */
|
|
||||||
|
|
||||||
if (!cg_controller_is_valid(controller))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
r = cg_all_unified();
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
if (r > 0) {
|
|
||||||
/* We don't support named hierarchies if we are using
|
|
||||||
* the unified hierarchy. */
|
|
||||||
|
|
||||||
if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (startswith(controller, "name="))
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
const char *cc, *dn;
|
|
||||||
|
|
||||||
dn = controller_to_dirname(controller);
|
dn = controller_to_dirname(controller);
|
||||||
cc = strjoina("/sys/fs/cgroup/", dn);
|
cpath = strjoina("/sys/fs/cgroup/", dn);
|
||||||
|
if (root)
|
||||||
|
/* Also check that:
|
||||||
|
* - possible subcgroup is created at root,
|
||||||
|
* - we can modify the hierarchy.
|
||||||
|
* "Leak" cpath on stack */
|
||||||
|
cpath = strjoina(cpath, root, "/cgroup.procs");
|
||||||
|
|
||||||
if (laccess(cc, F_OK) < 0)
|
if (laccess(cpath, root ? W_OK : F_OK) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -572,10 +553,23 @@ int cg_get_path_and_check(const char *controller, const char *path, const char *
|
|||||||
assert(controller);
|
assert(controller);
|
||||||
assert(fs);
|
assert(fs);
|
||||||
|
|
||||||
/* Check if the specified controller is actually accessible */
|
if (!cg_controller_is_valid(controller))
|
||||||
r = controller_is_accessible(controller);
|
return -EINVAL;
|
||||||
|
|
||||||
|
r = cg_all_unified();
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
if (r > 0) {
|
||||||
|
/* In the unified hierarchy all controllers are considered accessible,
|
||||||
|
* except for the named hierarchies */
|
||||||
|
if (startswith(controller, "name="))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
} else {
|
||||||
|
/* Check if the specified controller is actually accessible */
|
||||||
|
r = controller_is_v1_accessible(NULL, controller);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
return cg_get_path(controller, path, suffix, fs);
|
return cg_get_path(controller, path, suffix, fs);
|
||||||
}
|
}
|
||||||
@ -1892,7 +1886,7 @@ int cg_mask_from_string(const char *value, CGroupMask *ret) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cg_mask_supported(CGroupMask *ret) {
|
int cg_mask_supported_subtree(const char *root, CGroupMask *ret) {
|
||||||
CGroupMask mask;
|
CGroupMask mask;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -1904,15 +1898,11 @@ int cg_mask_supported(CGroupMask *ret) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
_cleanup_free_ char *root = NULL, *controllers = NULL, *path = NULL;
|
_cleanup_free_ char *controllers = NULL, *path = NULL;
|
||||||
|
|
||||||
/* In the unified hierarchy we can read the supported and accessible controllers from
|
/* In the unified hierarchy we can read the supported and accessible controllers from
|
||||||
* the top-level cgroup attribute */
|
* the top-level cgroup attribute */
|
||||||
|
|
||||||
r = cg_get_root_path(&root);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, root, "cgroup.controllers", &path);
|
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, root, "cgroup.controllers", &path);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -1931,7 +1921,7 @@ int cg_mask_supported(CGroupMask *ret) {
|
|||||||
} else {
|
} else {
|
||||||
CGroupController c;
|
CGroupController c;
|
||||||
|
|
||||||
/* In the legacy hierarchy, we check which hierarchies are mounted. */
|
/* In the legacy hierarchy, we check which hierarchies are accessible. */
|
||||||
|
|
||||||
mask = 0;
|
mask = 0;
|
||||||
for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
|
for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
|
||||||
@ -1942,7 +1932,7 @@ int cg_mask_supported(CGroupMask *ret) {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
n = cgroup_controller_to_string(c);
|
n = cgroup_controller_to_string(c);
|
||||||
if (controller_is_accessible(n) >= 0)
|
if (controller_is_v1_accessible(root, n) >= 0)
|
||||||
mask |= bit;
|
mask |= bit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1951,6 +1941,17 @@ int cg_mask_supported(CGroupMask *ret) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cg_mask_supported(CGroupMask *ret) {
|
||||||
|
_cleanup_free_ char *root = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = cg_get_root_path(&root);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return cg_mask_supported_subtree(root, ret);
|
||||||
|
}
|
||||||
|
|
||||||
int cg_kernel_controllers(Set **ret) {
|
int cg_kernel_controllers(Set **ret) {
|
||||||
_cleanup_set_free_free_ Set *controllers = NULL;
|
_cleanup_set_free_free_ Set *controllers = NULL;
|
||||||
_cleanup_fclose_ FILE *f = NULL;
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
@ -260,6 +260,7 @@ int cg_slice_to_path(const char *unit, char **ret);
|
|||||||
typedef const char* (*cg_migrate_callback_t)(CGroupMask mask, void *userdata);
|
typedef const char* (*cg_migrate_callback_t)(CGroupMask mask, void *userdata);
|
||||||
|
|
||||||
int cg_mask_supported(CGroupMask *ret);
|
int cg_mask_supported(CGroupMask *ret);
|
||||||
|
int cg_mask_supported_subtree(const char *root, CGroupMask *ret);
|
||||||
int cg_mask_from_string(const char *s, CGroupMask *ret);
|
int cg_mask_from_string(const char *s, CGroupMask *ret);
|
||||||
int cg_mask_to_string(CGroupMask mask, char **ret);
|
int cg_mask_to_string(CGroupMask mask, char **ret);
|
||||||
|
|
||||||
|
@ -1880,10 +1880,6 @@ int unit_pick_cgroup_path(Unit *u) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cg_v1_errno_to_log_level(int r) {
|
|
||||||
return r == -EROFS ? LOG_DEBUG : LOG_WARNING;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int unit_update_cgroup(
|
static int unit_update_cgroup(
|
||||||
Unit *u,
|
Unit *u,
|
||||||
CGroupMask target_mask,
|
CGroupMask target_mask,
|
||||||
@ -1941,30 +1937,16 @@ static int unit_update_cgroup(
|
|||||||
* We perform migration also with whole slices for cases when users don't care about leave
|
* We perform migration also with whole slices for cases when users don't care about leave
|
||||||
* granularity. Since delegated_mask is subset of target mask, we won't trim slice subtree containing
|
* granularity. Since delegated_mask is subset of target mask, we won't trim slice subtree containing
|
||||||
* delegated units.
|
* delegated units.
|
||||||
*
|
|
||||||
* If we're in an nspawn container and using legacy cgroups, the controller hierarchies are mounted
|
|
||||||
* read-only into the container. We skip migration/trim in this scenario since it would fail
|
|
||||||
* regardless with noisy "Read-only filesystem" warnings.
|
|
||||||
*/
|
*/
|
||||||
if (cg_all_unified() == 0) {
|
if (cg_all_unified() == 0) {
|
||||||
r = cg_migrate_v1_controllers(u->manager->cgroup_supported, migrate_mask, u->cgroup_path, migrate_callback, u);
|
r = cg_migrate_v1_controllers(u->manager->cgroup_supported, migrate_mask, u->cgroup_path, migrate_callback, u);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_unit_full_errno(
|
log_unit_warning_errno(u, r, "Failed to migrate controller cgroups from %s, ignoring: %m", u->cgroup_path);
|
||||||
u,
|
|
||||||
cg_v1_errno_to_log_level(r),
|
|
||||||
r,
|
|
||||||
"Failed to migrate controller cgroups from %s, ignoring: %m",
|
|
||||||
u->cgroup_path);
|
|
||||||
|
|
||||||
is_root_slice = unit_has_name(u, SPECIAL_ROOT_SLICE);
|
is_root_slice = unit_has_name(u, SPECIAL_ROOT_SLICE);
|
||||||
r = cg_trim_v1_controllers(u->manager->cgroup_supported, ~target_mask, u->cgroup_path, !is_root_slice);
|
r = cg_trim_v1_controllers(u->manager->cgroup_supported, ~target_mask, u->cgroup_path, !is_root_slice);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_unit_full_errno(
|
log_unit_warning_errno(u, r, "Failed to delete controller cgroups %s, ignoring: %m", u->cgroup_path);
|
||||||
u,
|
|
||||||
cg_v1_errno_to_log_level(r),
|
|
||||||
r,
|
|
||||||
"Failed to delete controller cgroups %s, ignoring: %m",
|
|
||||||
u->cgroup_path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set attributes */
|
/* Set attributes */
|
||||||
@ -3151,7 +3133,7 @@ int manager_setup_cgroup(Manager *m) {
|
|||||||
(void) cg_set_attribute("memory", "/", "memory.use_hierarchy", "1");
|
(void) cg_set_attribute("memory", "/", "memory.use_hierarchy", "1");
|
||||||
|
|
||||||
/* 8. Figure out which controllers are supported */
|
/* 8. Figure out which controllers are supported */
|
||||||
r = cg_mask_supported(&m->cgroup_supported);
|
r = cg_mask_supported_subtree(m->cgroup_root, &m->cgroup_supported);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to determine supported controllers: %m");
|
return log_error_errno(r, "Failed to determine supported controllers: %m");
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@ static int genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint16_t nl
|
|||||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||||
const NLType *genl_cmd_type, *nl_type;
|
const NLType *genl_cmd_type, *nl_type;
|
||||||
const NLTypeSystem *type_system;
|
const NLTypeSystem *type_system;
|
||||||
struct genlmsghdr *genl;
|
|
||||||
size_t size;
|
size_t size;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -63,9 +62,11 @@ static int genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint16_t nl
|
|||||||
m->hdr->nlmsg_type = nlmsg_type;
|
m->hdr->nlmsg_type = nlmsg_type;
|
||||||
|
|
||||||
type_get_type_system(nl_type, &m->containers[0].type_system);
|
type_get_type_system(nl_type, &m->containers[0].type_system);
|
||||||
genl = NLMSG_DATA(m->hdr);
|
|
||||||
genl->cmd = cmd;
|
*(struct genlmsghdr *) NLMSG_DATA(m->hdr) = (struct genlmsghdr) {
|
||||||
genl->version = genl_families[family].version;
|
.cmd = cmd,
|
||||||
|
.version = genl_families[family].version,
|
||||||
|
};
|
||||||
|
|
||||||
*ret = TAKE_PTR(m);
|
*ret = TAKE_PTR(m);
|
||||||
|
|
||||||
|
@ -144,7 +144,6 @@ static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *da
|
|||||||
size_t message_length;
|
size_t message_length;
|
||||||
struct nlmsghdr *new_hdr;
|
struct nlmsghdr *new_hdr;
|
||||||
struct rtattr *rta;
|
struct rtattr *rta;
|
||||||
unsigned i;
|
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
@ -172,7 +171,7 @@ static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *da
|
|||||||
rtattr_append_attribute_internal(rta, type, data, data_length);
|
rtattr_append_attribute_internal(rta, type, data, data_length);
|
||||||
|
|
||||||
/* if we are inside containers, extend them */
|
/* if we are inside containers, extend them */
|
||||||
for (i = 0; i < m->n_containers; i++)
|
for (unsigned i = 0; i < m->n_containers; i++)
|
||||||
GET_CONTAINER(m, i)->rta_len += RTA_SPACE(data_length);
|
GET_CONTAINER(m, i)->rta_len += RTA_SPACE(data_length);
|
||||||
|
|
||||||
/* update message size */
|
/* update message size */
|
||||||
@ -643,7 +642,6 @@ int sd_netlink_message_open_array(sd_netlink_message *m, uint16_t type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int sd_netlink_message_cancel_array(sd_netlink_message *m) {
|
int sd_netlink_message_cancel_array(sd_netlink_message *m) {
|
||||||
unsigned i;
|
|
||||||
uint32_t rta_len;
|
uint32_t rta_len;
|
||||||
|
|
||||||
assert_return(m, -EINVAL);
|
assert_return(m, -EINVAL);
|
||||||
@ -652,7 +650,7 @@ int sd_netlink_message_cancel_array(sd_netlink_message *m) {
|
|||||||
|
|
||||||
rta_len = GET_CONTAINER(m, (m->n_containers - 1))->rta_len;
|
rta_len = GET_CONTAINER(m, (m->n_containers - 1))->rta_len;
|
||||||
|
|
||||||
for (i = 0; i < m->n_containers; i++)
|
for (unsigned i = 0; i < m->n_containers; i++)
|
||||||
GET_CONTAINER(m, i)->rta_len -= rta_len;
|
GET_CONTAINER(m, i)->rta_len -= rta_len;
|
||||||
|
|
||||||
m->hdr->nlmsg_len -= rta_len;
|
m->hdr->nlmsg_len -= rta_len;
|
||||||
@ -1283,7 +1281,6 @@ int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *genl) {
|
|||||||
const NLType *nl_type;
|
const NLType *nl_type;
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
size_t size;
|
size_t size;
|
||||||
unsigned i;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert_return(m, -EINVAL);
|
assert_return(m, -EINVAL);
|
||||||
@ -1293,7 +1290,7 @@ int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *genl) {
|
|||||||
if (!m->sealed)
|
if (!m->sealed)
|
||||||
rtnl_message_seal(m);
|
rtnl_message_seal(m);
|
||||||
|
|
||||||
for (i = 1; i <= m->n_containers; i++)
|
for (unsigned i = 1; i <= m->n_containers; i++)
|
||||||
m->containers[i].attributes = mfree(m->containers[i].attributes);
|
m->containers[i].attributes = mfree(m->containers[i].attributes);
|
||||||
|
|
||||||
m->n_containers = 0;
|
m->n_containers = 0;
|
||||||
|
@ -29,7 +29,6 @@ int socket_open(int family) {
|
|||||||
static int broadcast_groups_get(sd_netlink *nl) {
|
static int broadcast_groups_get(sd_netlink *nl) {
|
||||||
_cleanup_free_ uint32_t *groups = NULL;
|
_cleanup_free_ uint32_t *groups = NULL;
|
||||||
socklen_t len = 0, old_len;
|
socklen_t len = 0, old_len;
|
||||||
unsigned i, j;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(nl);
|
assert(nl);
|
||||||
@ -37,11 +36,11 @@ static int broadcast_groups_get(sd_netlink *nl) {
|
|||||||
|
|
||||||
r = getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, NULL, &len);
|
r = getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, NULL, &len);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
if (errno == ENOPROTOOPT) {
|
if (errno != ENOPROTOOPT)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
nl->broadcast_group_dont_leave = true;
|
nl->broadcast_group_dont_leave = true;
|
||||||
return 0;
|
return 0;
|
||||||
} else
|
|
||||||
return -errno;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
@ -64,23 +63,15 @@ static int broadcast_groups_get(sd_netlink *nl) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
for (unsigned i = 0; i < len; i++)
|
||||||
for (j = 0; j < sizeof(uint32_t) * 8; j++) {
|
for (unsigned j = 0; j < sizeof(uint32_t) * 8; j++)
|
||||||
uint32_t offset;
|
if (groups[i] & (1U << j)) {
|
||||||
unsigned group;
|
unsigned group = i * sizeof(uint32_t) * 8 + j + 1;
|
||||||
|
|
||||||
offset = 1U << j;
|
|
||||||
|
|
||||||
if (!(groups[i] & offset))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
group = i * sizeof(uint32_t) * 8 + j + 1;
|
|
||||||
|
|
||||||
r = hashmap_put(nl->broadcast_group_refs, UINT_TO_PTR(group), UINT_TO_PTR(1));
|
r = hashmap_put(nl->broadcast_group_refs, UINT_TO_PTR(group), UINT_TO_PTR(1));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -104,11 +95,7 @@ int socket_bind(sd_netlink *nl) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
r = broadcast_groups_get(nl);
|
return broadcast_groups_get(nl);
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned broadcast_group_get_ref(sd_netlink *nl, unsigned group) {
|
static unsigned broadcast_group_get_ref(sd_netlink *nl, unsigned group) {
|
||||||
@ -130,17 +117,12 @@ static int broadcast_group_set_ref(sd_netlink *nl, unsigned group, unsigned n_re
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int broadcast_group_join(sd_netlink *nl, unsigned group) {
|
static int broadcast_group_join(sd_netlink *nl, unsigned group) {
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(nl);
|
assert(nl);
|
||||||
assert(nl->fd >= 0);
|
assert(nl->fd >= 0);
|
||||||
assert(group > 0);
|
assert(group > 0);
|
||||||
|
|
||||||
r = setsockopt(nl->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &group, sizeof(group));
|
/* group is "unsigned", but netlink(7) says the argument for NETLINK_ADD_MEMBERSHIP is "int" */
|
||||||
if (r < 0)
|
return setsockopt_int(nl->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, group);
|
||||||
return -errno;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int socket_broadcast_group_ref(sd_netlink *nl, unsigned group) {
|
int socket_broadcast_group_ref(sd_netlink *nl, unsigned group) {
|
||||||
@ -173,8 +155,6 @@ int socket_broadcast_group_ref(sd_netlink *nl, unsigned group) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int broadcast_group_leave(sd_netlink *nl, unsigned group) {
|
static int broadcast_group_leave(sd_netlink *nl, unsigned group) {
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(nl);
|
assert(nl);
|
||||||
assert(nl->fd >= 0);
|
assert(nl->fd >= 0);
|
||||||
assert(group > 0);
|
assert(group > 0);
|
||||||
@ -182,11 +162,8 @@ static int broadcast_group_leave(sd_netlink *nl, unsigned group) {
|
|||||||
if (nl->broadcast_group_dont_leave)
|
if (nl->broadcast_group_dont_leave)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = setsockopt(nl->fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP, &group, sizeof(group));
|
/* group is "unsigned", but netlink(7) says the argument for NETLINK_DROP_MEMBERSHIP is "int" */
|
||||||
if (r < 0)
|
return setsockopt_int(nl->fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP, group);
|
||||||
return -errno;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int socket_broadcast_group_unref(sd_netlink *nl, unsigned group) {
|
int socket_broadcast_group_unref(sd_netlink *nl, unsigned group) {
|
||||||
@ -240,8 +217,6 @@ int socket_write_message(sd_netlink *nl, sd_netlink_message *m) {
|
|||||||
|
|
||||||
int socket_writev_message(sd_netlink *nl, sd_netlink_message **m, size_t msgcount) {
|
int socket_writev_message(sd_netlink *nl, sd_netlink_message **m, size_t msgcount) {
|
||||||
_cleanup_free_ struct iovec *iovs = NULL;
|
_cleanup_free_ struct iovec *iovs = NULL;
|
||||||
ssize_t k;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
assert(nl);
|
assert(nl);
|
||||||
assert(m);
|
assert(m);
|
||||||
@ -251,13 +226,13 @@ int socket_writev_message(sd_netlink *nl, sd_netlink_message **m, size_t msgcoun
|
|||||||
if (!iovs)
|
if (!iovs)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (i = 0; i < msgcount; i++) {
|
for (size_t i = 0; i < msgcount; i++) {
|
||||||
assert(m[i]->hdr != NULL);
|
assert(m[i]->hdr != NULL);
|
||||||
assert(m[i]->hdr->nlmsg_len > 0);
|
assert(m[i]->hdr->nlmsg_len > 0);
|
||||||
iovs[i] = IOVEC_MAKE(m[i]->hdr, m[i]->hdr->nlmsg_len);
|
iovs[i] = IOVEC_MAKE(m[i]->hdr, m[i]->hdr->nlmsg_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
k = writev(nl->fd, iovs, msgcount);
|
ssize_t k = writev(nl->fd, iovs, msgcount);
|
||||||
if (k < 0)
|
if (k < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
@ -325,7 +300,6 @@ int socket_read_message(sd_netlink *rtnl) {
|
|||||||
struct iovec iov = {};
|
struct iovec iov = {};
|
||||||
uint32_t group = 0;
|
uint32_t group = 0;
|
||||||
bool multi_part = false, done = false;
|
bool multi_part = false, done = false;
|
||||||
struct nlmsghdr *new_msg;
|
|
||||||
size_t len;
|
size_t len;
|
||||||
int r;
|
int r;
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
@ -372,7 +346,7 @@ int socket_read_message(sd_netlink *rtnl) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
|
for (struct nlmsghdr *new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
|
||||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||||
const NLType *nl_type;
|
const NLType *nl_type;
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
static int nft_message_new(sd_netlink *nfnl, sd_netlink_message **ret, int family, uint16_t type, uint16_t flags) {
|
static int nft_message_new(sd_netlink *nfnl, sd_netlink_message **ret, int family, uint16_t type, uint16_t flags) {
|
||||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||||
struct nfgenmsg *nfh;
|
|
||||||
const NLType *nl_type;
|
const NLType *nl_type;
|
||||||
size_t size;
|
size_t size;
|
||||||
int r;
|
int r;
|
||||||
@ -57,10 +56,11 @@ static int nft_message_new(sd_netlink *nfnl, sd_netlink_message **ret, int famil
|
|||||||
m->hdr->nlmsg_len = size;
|
m->hdr->nlmsg_len = size;
|
||||||
m->hdr->nlmsg_type = NFNL_SUBSYS_NFTABLES << 8 | type;
|
m->hdr->nlmsg_type = NFNL_SUBSYS_NFTABLES << 8 | type;
|
||||||
|
|
||||||
nfh = NLMSG_DATA(m->hdr);
|
*(struct nfgenmsg*) NLMSG_DATA(m->hdr) = (struct nfgenmsg) {
|
||||||
nfh->nfgen_family = family;
|
.nfgen_family = family,
|
||||||
nfh->version = NFNETLINK_V0;
|
.version = NFNETLINK_V0,
|
||||||
nfh->res_id = nfnl->serial;
|
.res_id = nfnl->serial,
|
||||||
|
};
|
||||||
|
|
||||||
*ret = TAKE_PTR(m);
|
*ret = TAKE_PTR(m);
|
||||||
return 0;
|
return 0;
|
||||||
@ -68,17 +68,17 @@ static int nft_message_new(sd_netlink *nfnl, sd_netlink_message **ret, int famil
|
|||||||
|
|
||||||
static int sd_nfnl_message_batch(sd_netlink *nfnl, sd_netlink_message **ret, int v) {
|
static int sd_nfnl_message_batch(sd_netlink *nfnl, sd_netlink_message **ret, int v) {
|
||||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||||
struct nfgenmsg *nfh;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = message_new(nfnl, &m, v);
|
r = message_new(nfnl, &m, v);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
nfh = NLMSG_DATA(m->hdr);
|
*(struct nfgenmsg*) NLMSG_DATA(m->hdr) = (struct nfgenmsg) {
|
||||||
nfh->nfgen_family = AF_UNSPEC;
|
.nfgen_family = AF_UNSPEC,
|
||||||
nfh->version = NFNETLINK_V0;
|
.version = NFNETLINK_V0,
|
||||||
nfh->res_id = NFNL_SUBSYS_NFTABLES;
|
.res_id = NFNL_SUBSYS_NFTABLES,
|
||||||
|
};
|
||||||
|
|
||||||
*ret = TAKE_PTR(m);
|
*ret = TAKE_PTR(m);
|
||||||
return r;
|
return r;
|
||||||
|
@ -4,4 +4,15 @@ TEST_DESCRIPTION="Tmpfiles related tests"
|
|||||||
TEST_NO_QEMU=1
|
TEST_NO_QEMU=1
|
||||||
. $TEST_BASE_DIR/test-functions
|
. $TEST_BASE_DIR/test-functions
|
||||||
|
|
||||||
|
test_append_files() {
|
||||||
|
if [[ "$IS_BUILT_WITH_ASAN" == "yes" ]]; then
|
||||||
|
if [[ -z "$initdir" ]]; then
|
||||||
|
echo >&2 "\$initdir is not defined, can't continue"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sed -i "s/systemd//g" "$initdir/etc/nsswitch.conf"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
do_test "$@" 22
|
do_test "$@" 22
|
||||||
|
Loading…
x
Reference in New Issue
Block a user