1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-31 14:50:15 +03:00

pid1: add DumpFileDescriptorStore() bus call that returns fdstore content info

This commit is contained in:
Lennart Poettering 2023-03-27 18:16:40 +02:00
parent 522f12224c
commit 2ea24611b9
7 changed files with 119 additions and 0 deletions

View File

@ -273,6 +273,8 @@ node /org/freedesktop/systemd1 {
LookupDynamicUserByUID(in u uid,
out s name);
GetDynamicUsers(out a(us) users);
DumpUnitFileDescriptorStore(in s name,
out a(suuutuusu) entries);
signals:
UnitNew(s id,
o unit);
@ -974,6 +976,8 @@ node /org/freedesktop/systemd1 {
<variablelist class="dbus-method" generated="True" extra-ref="GetDynamicUsers()"/>
<variablelist class="dbus-method" generated="True" extra-ref="DumpUnitFileDescriptorStore()"/>
<variablelist class="dbus-signal" generated="True" extra-ref="UnitNew"/>
<variablelist class="dbus-signal" generated="True" extra-ref="UnitRemoved"/>
@ -1531,6 +1535,11 @@ node /org/freedesktop/systemd1 {
<ulink url="https://www.freedesktop.org/wiki/Software/systemd/ControlGroupInterface">New Control Group
Interface</ulink> for more information how to make use of this functionality for resource control
purposes.</para>
<para><function>DumpUnitFileDescriptorStore()</function> returns an array with information about the
file descriptors currently in the file descriptor store of the specified unit. This call is equivalent
to <function>DumpFileDescriptorStore()</function> on the
<interfacename>org.freedesktop.systemd1.Service</interfacename>. For further details, see below.</para>
</refsect2>
<refsect2>
@ -2548,6 +2557,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
in b read_only,
in b mkdir,
in a(ss) options);
DumpFileDescriptorStore(out a(suuutuusu) entries);
GetProcesses(out a(sus) processes);
AttachProcesses(in s subcgroup,
in au pids);
@ -3742,6 +3752,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<variablelist class="dbus-method" generated="True" extra-ref="MountImage()"/>
<variablelist class="dbus-method" generated="True" extra-ref="DumpFileDescriptorStore()"/>
<variablelist class="dbus-method" generated="True" extra-ref="GetProcesses()"/>
<variablelist class="dbus-method" generated="True" extra-ref="AttachProcesses()"/>
@ -4393,6 +4405,16 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
directly on the Manager object has the advantage of not requiring a <function>GetUnit()</function> call
to get the unit object for a specific unit name. Calling the methods on the Manager object is hence a round
trip optimization.</para>
<para><function>DumpFileDescriptorStore()</function> returns an array with information about the file
descriptors currently in the file descriptor store of the service. Each entry consists of a file
descriptor name (i.e. the <varname>FDNAME=</varname> field), the file descriptor inode type and access
mode as integer (i.e. a <type>mode_t</type> value, flags such as <constant>S_IFREG</constant>,
<constant>S_IRUSR</constant>, …), the major and minor numbers of the device number of the file system
backing the inode of the file descriptor, the inode number, the major and minor numbers of the device
number if this refers to a character or block device node, a file system path pointing to the inode,
and the file descriptor flags (i.e. <constant>O_RDWR</constant>, <constant>O_RDONLY</constant>,
…).</para>
</refsect2>
<refsect2>

View File

@ -58,3 +58,12 @@
#ifndef O_TMPFILE
#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
#endif
/* So O_LARGEFILE is generally implied by glibc, and defined to zero hence, because we only build in LFS
* mode. However, when invoking fcntl(F_GETFL) the flag is ORed into the result anyway glibc does not mask
* it away. Which sucks. Let's define the actual value here, so that we can mask it ourselves. */
#if O_LARGEFILE != 0
#define RAW_O_LARGEFILE O_LARGEFILE
#else
#define RAW_O_LARGEFILE 0100000
#endif

View File

@ -2840,6 +2840,10 @@ static int method_set_show_status(sd_bus_message *message, void *userdata, sd_bu
return sd_bus_reply_method_return(message, NULL);
}
static int method_dump_unit_descriptor_store(sd_bus_message *message, void *userdata, sd_bus_error *error) {
return method_generic_unit_operation(message, userdata, error, bus_service_method_dump_file_descriptor_store, 0);
}
const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_VTABLE_START(0),
@ -3385,6 +3389,11 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_RESULT("a(us)", users),
method_get_dynamic_users,
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_ARGS("DumpUnitFileDescriptorStore",
SD_BUS_ARGS("s", name),
SD_BUS_RESULT("a(suuutuusu)", entries),
method_dump_unit_descriptor_store,
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_SIGNAL_WITH_ARGS("UnitNew",
SD_BUS_ARGS("s", id, "o", unit),

View File

@ -4,6 +4,7 @@
#include "alloc-util.h"
#include "async.h"
#include "bus-common-errors.h"
#include "bus-get-properties.h"
#include "dbus-cgroup.h"
#include "dbus-execute.h"
@ -16,6 +17,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "locale-util.h"
#include "missing_fcntl.h"
#include "mount-util.h"
#include "open-file.h"
#include "parse-util.h"
@ -218,6 +220,72 @@ int bus_service_method_mount_image(sd_bus_message *message, void *userdata, sd_b
return bus_service_method_mount(message, userdata, error, true);
}
int bus_service_method_dump_file_descriptor_store(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Service *s = ASSERT_PTR(userdata);
int r;
assert(message);
r = mac_selinux_unit_access_check(UNIT(s), message, "status", error);
if (r < 0)
return r;
if (s->n_fd_store_max == 0 && s->n_fd_store == 0)
return sd_bus_error_setf(error, BUS_ERROR_FILE_DESCRIPTOR_STORE_DISABLED, "File descriptor store not enabled for %s.", UNIT(s)->id);
r = sd_bus_message_new_method_return(message, &reply);
if (r < 0)
return r;
r = sd_bus_message_open_container(reply, 'a', "(suuutuusu)");
if (r < 0)
return r;
LIST_FOREACH(fd_store, i, s->fd_store) {
_cleanup_free_ char *path = NULL;
struct stat st;
int flags;
if (fstat(i->fd, &st) < 0) {
log_debug_errno(errno, "Failed to stat() file descriptor entry '%s', skipping.", strna(i->fdname));
continue;
}
flags = fcntl(i->fd, F_GETFL);
if (flags < 0) {
log_debug_errno(errno, "Failed to issue F_GETFL on file descriptor entry '%s', skipping.", strna(i->fdname));
continue;
}
/* glibc implies O_LARGEFILE everywhere on 64bit off_t builds, but forgets to hide it away on
* F_GETFL, but provides no definition to check for that. Let's mask the flag away manually,
* to not confuse clients. */
flags &= ~RAW_O_LARGEFILE;
(void) fd_get_path(i->fd, &path);
r = sd_bus_message_append(
reply,
"(suuutuusu)",
i->fdname,
(uint32_t) st.st_mode,
(uint32_t) major(st.st_dev), (uint32_t) minor(st.st_dev),
(uint64_t) st.st_ino,
(uint32_t) major(st.st_rdev), (uint32_t) minor(st.st_rdev),
path,
(uint32_t) flags);
if (r < 0)
return r;
}
r = sd_bus_message_close_container(reply);
if (r < 0)
return r;
return sd_bus_send(NULL, reply, NULL);
}
const sd_bus_vtable bus_service_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), SD_BUS_VTABLE_PROPERTY_CONST),
@ -292,6 +360,12 @@ const sd_bus_vtable bus_service_vtable[] = {
bus_service_method_mount_image,
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_ARGS("DumpFileDescriptorStore",
SD_BUS_NO_ARGS,
SD_BUS_ARGS("a(suuutuusu)", entries),
bus_service_method_dump_file_descriptor_store,
SD_BUS_VTABLE_UNPRIVILEGED),
/* The following four are obsolete, and thus marked hidden here. They moved into the Unit interface */
SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_ratelimit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_ratelimit.burst), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),

View File

@ -12,3 +12,4 @@ int bus_service_set_property(Unit *u, const char *name, sd_bus_message *i, UnitW
int bus_service_method_bind_mount(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_service_method_mount_image(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_service_commit_properties(Unit *u);
int bus_service_method_dump_file_descriptor_store(sd_bus_message *message, void *userdata, sd_bus_error *error);

View File

@ -32,6 +32,8 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DYNAMIC_USER, ESRCH),
SD_BUS_ERROR_MAP(BUS_ERROR_NOT_REFERENCED, EUNATCH),
SD_BUS_ERROR_MAP(BUS_ERROR_DISK_FULL, ENOSPC),
SD_BUS_ERROR_MAP(BUS_ERROR_FILE_DESCRIPTOR_STORE_DISABLED,
EHOSTDOWN),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_MACHINE, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_IMAGE, ENOENT),

View File

@ -32,6 +32,8 @@
#define BUS_ERROR_UNIT_BUSY "org.freedesktop.systemd1.UnitBusy"
#define BUS_ERROR_UNIT_INACTIVE "org.freedesktop.systemd1.UnitInactive"
#define BUS_ERROR_FREEZE_CANCELLED "org.freedesktop.systemd1.FreezeCancelled"
#define BUS_ERROR_FILE_DESCRIPTOR_STORE_DISABLED \
"org.freedesktop.systemd1.FileDescriptorStoreDisabled"
#define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine"
#define BUS_ERROR_NO_SUCH_IMAGE "org.freedesktop.machine1.NoSuchImage"