1
0
mirror of https://github.com/systemd/systemd synced 2025-10-03 18:54:45 +02:00

Compare commits

...

3 Commits

Author SHA1 Message Date
Michal Sekletar
43b4e3058c install: refactor find_symlinks() and don't search for symlinks recursively
After all we are only interested in symlinks either in top-level config
directory or in .wants and .requires sub-directories.

As a bonus this should speed up ListUnitFiles() roughly 3-4x on systems
with a lot of units that use drop-ins (e.g. SSH jump hosts with a lot of
user session scopes).
2021-03-11 13:12:37 +01:00
Lennart Poettering
170c659338 man: shorten list of partition types a bit
Tables with only one column aren't really tables, they are lists. And if
each cell only consists of a single word, they are probably better
written in a single line. Hence, shorten the man page a bit, and list
boot loader spec partition types in a simple sentence.

Also, drop "root-secondary" from the list. When dissecting images we'll
upgrade "root-secondary" to "root" if we mount it, and do so only if
"root" doesn't exist. Hence never mention "root-secondary" as we never
will mount a partition under that id.
2021-03-11 12:04:13 +01:00
Lennart Poettering
48f813c4aa coredumpctl: fflush() stdout before invoking gdb
Fixes: #18936
2021-03-11 08:55:20 +01:00
5 changed files with 106 additions and 150 deletions

View File

@ -173,50 +173,11 @@
<citerefentry project='man-pages'><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
</para>
<para>Valid partition names follow the <ulink url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable
Partitions Specification</ulink>.</para>
<table>
<title>Accepted partition names</title>
<tgroup cols='1'>
<colspec colname='partition' />
<thead>
<row>
<entry>Partition Name</entry>
</row>
</thead>
<tbody>
<row>
<entry>root</entry>
</row>
<row>
<entry>root-secondary</entry>
</row>
<row>
<entry>home</entry>
</row>
<row>
<entry>srv</entry>
</row>
<row>
<entry>esp</entry>
</row>
<row>
<entry>xbootldr</entry>
</row>
<row>
<entry>tmp</entry>
</row>
<row>
<entry>var</entry>
</row>
<row>
<entry>usr</entry>
</row>
</tbody>
</tgroup>
</table>
<para>Valid partition names follow the <ulink
url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable Partitions Specification</ulink>:
<constant>root</constant>, <constant>usr</constant>, <constant>home</constant>, <constant>srv</constant>,
<constant>esp</constant>, <constant>xbootldr</constant>, <constant>tmp</constant>,
<constant>var</constant>.</para>
<xi:include href="system-only.xml" xpointer="singular"/></listitem>
</varlistentry>

View File

@ -1230,6 +1230,11 @@ int safe_fork_full(
original_pid = getpid_cached();
if (flags & FORK_FLUSH_STDIO) {
fflush(stdout);
fflush(stderr); /* This one shouldn't be necessary, stderr should be unbuffered anyway, but let's better be safe than sorry */
}
if (flags & (FORK_RESET_SIGNALS|FORK_DEATHSIG)) {
/* We temporarily block all signals, so that the new child has them blocked initially. This way, we can
* be sure that SIGTERMs are not lost we might send to the child. */

View File

@ -162,6 +162,7 @@ typedef enum ForkFlags {
FORK_MOUNTNS_SLAVE = 1 << 9, /* Make child's mount namespace MS_SLAVE */
FORK_RLIMIT_NOFILE_SAFE = 1 << 10, /* Set RLIMIT_NOFILE soft limit to 1K for select() compat */
FORK_STDOUT_TO_STDERR = 1 << 11, /* Make stdout a copy of stderr */
FORK_FLUSH_STDIO = 1 << 12, /* fflush() stdout (and stderr) before forking */
} ForkFlags;
int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);

View File

@ -1116,7 +1116,7 @@ static int run_debug(int argc, char **argv, void *userdata) {
fork_name = strjoina("(", debugger_call[0], ")");
r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_FLUSH_STDIO, &pid);
if (r < 0)
goto finish;
if (r == 0) {

View File

@ -705,132 +705,88 @@ static int is_symlink_with_known_name(const UnitFileInstallInfo *i, const char *
return false;
}
static int find_symlinks_fd(
static int find_symlinks_in_directory(
DIR *dir,
const char *dir_path,
const char *root_dir,
const UnitFileInstallInfo *i,
bool match_aliases,
bool ignore_same_name,
int fd,
const char *path,
const char *config_path,
bool *same_name_link) {
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
int r = 0;
assert(i);
assert(fd >= 0);
assert(path);
assert(config_path);
assert(same_name_link);
FOREACH_DIRENT(de, dir, return -errno) {
_cleanup_free_ char *dest = NULL;
bool found_path = false, found_dest, b = false;
int q;
d = fdopendir(fd);
if (!d) {
safe_close(fd);
return -errno;
}
dirent_ensure_type(dir, de);
FOREACH_DIRENT(de, d, return -errno) {
if (de->d_type != DT_LNK)
continue;
dirent_ensure_type(d, de);
if (de->d_type == DT_DIR) {
_cleanup_free_ char *p = NULL;
int nfd, q;
nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
if (nfd < 0) {
if (errno == ENOENT)
continue;
if (r == 0)
r = -errno;
continue;
}
p = path_make_absolute(de->d_name, path);
if (!p) {
safe_close(nfd);
return -ENOMEM;
}
/* This will close nfd, regardless whether it succeeds or not */
q = find_symlinks_fd(root_dir, i, match_aliases, ignore_same_name, nfd,
p, config_path, same_name_link);
if (q > 0)
return 1;
/* Acquire symlink destination */
q = readlinkat_malloc(dirfd(dir), de->d_name, &dest);
if (q == -ENOENT)
continue;
if (q < 0) {
if (r == 0)
r = q;
continue;
}
} else if (de->d_type == DT_LNK) {
_cleanup_free_ char *p = NULL, *dest = NULL;
bool found_path = false, found_dest, b = false;
int q;
/* Make absolute */
if (!path_is_absolute(dest)) {
char *x;
/* Acquire symlink name */
p = path_make_absolute(de->d_name, path);
if (!p)
x = path_join(dir_path, dest);
if (!x)
return -ENOMEM;
/* Acquire symlink destination */
q = readlink_malloc(p, &dest);
if (q == -ENOENT)
continue;
if (q < 0) {
if (r == 0)
r = q;
continue;
}
free_and_replace(dest, x);
}
/* Make absolute */
if (!path_is_absolute(dest)) {
char *x;
assert(unit_name_is_valid(i->name, UNIT_NAME_ANY));
if (!ignore_same_name)
/* Check if the symlink itself matches what we are looking for.
*
* If ignore_same_name is specified, we are in one of the directories which
* have lower priority than the unit file, and even if a file or symlink with
* this name was found, we should ignore it. */
found_path = streq(de->d_name, i->name);
x = path_join(root_dir, dest);
if (!x)
return -ENOMEM;
/* Check if what the symlink points to matches what we are looking for */
found_dest = streq(basename(dest), i->name);
free_and_replace(dest, x);
}
if (found_path && found_dest) {
_cleanup_free_ char *p = NULL, *t = NULL;
assert(unit_name_is_valid(i->name, UNIT_NAME_ANY));
if (!ignore_same_name)
/* Check if the symlink itself matches what we are looking for.
*
* If ignore_same_name is specified, we are in one of the directories which
* have lower priority than the unit file, and even if a file or symlink with
* this name was found, we should ignore it. */
found_path = streq(de->d_name, i->name);
/* Filter out same name links in the main
* config path */
p = path_make_absolute(de->d_name, dir_path);
t = path_make_absolute(i->name, config_path);
/* Check if what the symlink points to matches what we are looking for */
found_dest = streq(basename(dest), i->name);
if (!p || !t)
return -ENOMEM;
if (found_path && found_dest) {
_cleanup_free_ char *t = NULL;
b = path_equal(p, t);
}
/* Filter out same name links in the main
* config path */
t = path_make_absolute(i->name, config_path);
if (!t)
return -ENOMEM;
if (b)
*same_name_link = true;
else if (found_path || found_dest) {
if (!match_aliases)
return 1;
b = path_equal(t, p);
}
if (b)
*same_name_link = true;
else if (found_path || found_dest) {
if (!match_aliases)
return 1;
/* Check if symlink name is in the set of names used by [Install] */
q = is_symlink_with_known_name(i, de->d_name);
if (q < 0)
return q;
if (q > 0)
return 1;
}
/* Check if symlink name is in the set of names used by [Install] */
q = is_symlink_with_known_name(i, de->d_name);
if (q < 0)
return q;
if (q > 0)
return 1;
}
}
@ -845,22 +801,55 @@ static int find_symlinks(
const char *config_path,
bool *same_name_link) {
int fd;
_cleanup_closedir_ DIR *config_dir = NULL;
struct dirent *de;
int r = 0;
assert(i);
assert(config_path);
assert(same_name_link);
fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC);
if (fd < 0) {
config_dir = opendir(config_path);
if (!config_dir) {
if (IN_SET(errno, ENOENT, ENOTDIR, EACCES))
return 0;
return -errno;
}
/* This takes possession of fd and closes it */
return find_symlinks_fd(root_dir, i, match_name, ignore_same_name, fd,
config_path, config_path, same_name_link);
FOREACH_DIRENT(de, config_dir, return -errno) {
const char *suffix;
_cleanup_free_ const char *path = NULL;
_cleanup_closedir_ DIR *d = NULL;
dirent_ensure_type(config_dir, de);
if (de->d_type != DT_DIR)
continue;
suffix = strrchr(de->d_name, '.');
if (!STRPTR_IN_SET(suffix, ".wants", ".requires"))
continue;
path = path_join(config_path, de->d_name);
if (!path)
return -ENOMEM;
d = opendir(path);
if (!d) {
log_error_errno(errno, "Failed to open directory '%s' while scanning for symlinks, ignoring: %m", path);
continue;
}
r = find_symlinks_in_directory(d, path, root_dir, i, match_name, ignore_same_name, config_path, same_name_link);
if (r > 0)
return 1;
else if (r < 0)
log_debug_errno(r, "Failed to lookup for symlinks in '%s': %m", path);
}
/* We didn't find any suitable symlinks in .wants or .requires directories, let's look for linked unit files in this directory. */
rewinddir(config_dir);
return find_symlinks_in_directory(config_dir, config_path, root_dir, i, match_name, ignore_same_name, config_path, same_name_link);
}
static int find_symlinks_in_scope(