• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 15263807472

26 May 2025 08:53PM UTC coverage: 72.046% (-0.002%) from 72.048%
15263807472

push

github

yuwata
src/core/manager.c: log preset activity on first boot

This gives us a little more information about what units were enabled
or disabled on that first boot and will be useful for OS developers
tracking down the source of unit state.

An example with this enabled looks like:

```
NET: Registered PF_VSOCK protocol family
systemd[1]: Applying preset policy.
systemd[1]: Unit /etc/systemd/system/dnsmasq.service is masked, ignoring.
systemd[1]: Unit /etc/systemd/system/systemd-repart.service is masked, ignoring.
systemd[1]: Removed '/etc/systemd/system/sockets.target.wants/systemd-resolved-monitor.socket'.
systemd[1]: Removed '/etc/systemd/system/sockets.target.wants/systemd-resolved-varlink.socket'.
systemd[1]: Created symlink '/etc/systemd/system/multi-user.target.wants/var-mnt-workdir.mount' → '/etc/systemd/system/var-mnt-workdir.mount'.
systemd[1]: Created symlink '/etc/systemd/system/multi-user.target.wants/var-mnt-workdir\x2dtmp.mount' → '/etc/systemd/system/var-mnt-workdir\x2dtmp.mount'.
systemd[1]: Created symlink '/etc/systemd/system/afterburn-sshkeys.target.requires/afterburn-sshkeys@core.service' → '/usr/lib/systemd/system/afterburn-sshkeys@.service'.
systemd[1]: Created symlink '/etc/systemd/system/sockets.target.wants/systemd-resolved-varlink.socket' → '/usr/lib/systemd/system/systemd-resolved-varlink.socket'.
systemd[1]: Created symlink '/etc/systemd/system/sockets.target.wants/systemd-resolved-monitor.socket' → '/usr/lib/systemd/system/systemd-resolved-monitor.socket'.
systemd[1]: Populated /etc with preset unit settings.
```

Considering it only happens on first boot and not on every boot I think
the extra information is worth the extra verbosity in the logs just for
that boot.

5 of 6 new or added lines in 1 file covered. (83.33%)

5463 existing lines in 165 files now uncovered.

299151 of 415222 relevant lines covered (72.05%)

702386.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.38
/src/basic/lock-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <fcntl.h>
4
#include <signal.h>
5
#include <stdio.h>
6
#include <stdlib.h>
7
#include <string.h>
8
#include <sys/file.h>
9

10
#include "alloc-util.h"
11
#include "errno-util.h"
12
#include "fd-util.h"
13
#include "fs-util.h"
14
#include "lock-util.h"
15
#include "log.h"
16
#include "path-util.h"
17
#include "process-util.h"
18
#include "string-util.h"
19
#include "time-util.h"
20

21
int make_lock_file_at(int dir_fd, const char *p, int operation, LockFile *ret) {
242,832✔
22
        _cleanup_close_ int fd = -EBADF, dfd = -EBADF;
242,832✔
23
        _cleanup_free_ char *t = NULL;
242,832✔
24

25
        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
242,832✔
26
        assert(p);
242,832✔
27
        assert(IN_SET(operation & ~LOCK_NB, LOCK_EX, LOCK_SH));
242,832✔
28
        assert(ret);
242,832✔
29

30
        if (isempty(p))
485,664✔
31
                return -EINVAL;
32

33
        /* We use UNPOSIX locks as they have nice semantics, and are mostly compatible with NFS. */
34

35
        dfd = fd_reopen(dir_fd, O_CLOEXEC|O_PATH|O_DIRECTORY);
242,832✔
36
        if (dfd < 0)
242,832✔
37
                return dfd;
38

39
        t = strdup(p);
242,832✔
40
        if (!t)
242,832✔
41
                return -ENOMEM;
42

43
        fd = xopenat_lock_full(dfd,
242,832✔
44
                               p,
45
                               O_CREAT|O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NOCTTY,
46
                               /* xopen_flags = */ 0,
47
                               0600,
48
                               LOCK_UNPOSIX,
49
                               operation);
50
        if (fd < 0)
242,832✔
51
                return fd == -EAGAIN ? -EBUSY : fd;
3✔
52

53
        *ret = (LockFile) {
242,829✔
54
                .dir_fd = TAKE_FD(dfd),
242,829✔
55
                .path = TAKE_PTR(t),
242,829✔
56
                .fd = TAKE_FD(fd),
242,829✔
57
                .operation = operation,
58
        };
59

60
        return 0;
242,829✔
61
}
62

63
int make_lock_file_for(const char *p, int operation, LockFile *ret) {
629✔
64
        _cleanup_free_ char *fn = NULL, *dn = NULL, *t = NULL;
629✔
65
        int r;
629✔
66

67
        assert(p);
629✔
68
        assert(ret);
629✔
69

70
        r = path_extract_filename(p, &fn);
629✔
71
        if (r < 0)
629✔
72
                return r;
73

74
        r = path_extract_directory(p, &dn);
629✔
75
        if (r < 0)
629✔
76
                return r;
77

78
        t = strjoin(dn, "/.#", fn, ".lck");
629✔
79
        if (!t)
629✔
80
                return -ENOMEM;
81

82
        return make_lock_file(t, operation, ret);
629✔
83
}
84

85
void release_lock_file(LockFile *f) {
485,011✔
86
        if (!f)
485,011✔
87
                return;
88

89
        if (f->path) {
485,011✔
90

91
                /* If we are the exclusive owner we can safely delete
92
                 * the lock file itself. If we are not the exclusive
93
                 * owner, we can try becoming it. */
94

95
                if (f->fd >= 0 &&
242,414✔
96
                    (f->operation & ~LOCK_NB) == LOCK_SH &&
242,882✔
97
                    unposix_lock(f->fd, LOCK_EX|LOCK_NB) >= 0)
468✔
98
                        f->operation = LOCK_EX|LOCK_NB;
467✔
99

100
                if ((f->operation & ~LOCK_NB) == LOCK_EX)
242,414✔
101
                        (void) unlinkat(f->dir_fd, f->path, 0);
242,413✔
102

103
                f->path = mfree(f->path);
242,414✔
104
        }
105

106
        f->dir_fd = safe_close(f->dir_fd);
485,011✔
107
        f->fd = safe_close(f->fd);
485,011✔
108
        f->operation = 0;
485,011✔
109
}
110

111
static int fcntl_lock(int fd, int operation, bool ofd) {
261,833✔
112
        int cmd, type, r;
261,833✔
113

114
        assert(fd >= 0);
261,833✔
115

116
        if (ofd)
261,833✔
117
                cmd = (operation & LOCK_NB) ? F_OFD_SETLK : F_OFD_SETLKW;
261,424✔
118
        else
119
                cmd = (operation & LOCK_NB) ? F_SETLK : F_SETLKW;
409✔
120

121
        switch (operation & ~LOCK_NB) {
261,833✔
122
                case LOCK_EX:
123
                        type = F_WRLCK;
124
                        break;
125
                case LOCK_SH:
504✔
126
                        type = F_RDLCK;
504✔
127
                        break;
504✔
128
                case LOCK_UN:
204✔
129
                        type = F_UNLCK;
204✔
130
                        break;
204✔
UNCOV
131
                default:
×
UNCOV
132
                        assert_not_reached();
×
133
        }
134

135
        r = RET_NERRNO(fcntl(fd, cmd, &(struct flock) {
261,833✔
136
                .l_type = type,
137
                .l_whence = SEEK_SET,
138
                .l_start = 0,
139
                .l_len = 0,
140
        }));
141

142
        /* If we are doing non-blocking operations, treat EACCES/EAGAIN the same as per man page. But if
143
         * not, propagate EACCES back, as it will likely be due to an LSM denying the operation (for example
144
         * LXC with AppArmor when running on kernel < 6.2), and in some cases we want to gracefully
145
         * fallback (e.g.: PrivateNetwork=yes). As per documentation, it's only the non-blocking operation
146
         * F_SETLK that might return EACCES on some platforms (although the Linux implementation doesn't
147
         * seem to), as F_SETLKW and F_OFD_SETLKW block so this is not an issue, and F_OFD_SETLK is documented
148
         * to only return EAGAIN if the lock is already held. */
149
        if ((operation & LOCK_NB) && r == -EACCES)
261,833✔
UNCOV
150
                r = -EAGAIN;
×
151

152
        return r;
261,833✔
153
}
154

155
int posix_lock(int fd, int operation) {
261✔
156
        return fcntl_lock(fd, operation, /*ofd=*/ false);
261✔
157
}
158

159
int unposix_lock(int fd, int operation) {
261,424✔
160
        return fcntl_lock(fd, operation, /*ofd=*/ true);
261,424✔
161
}
162

163
void posix_unlockpp(int **fd) {
148✔
164
        assert(fd);
148✔
165

166
        if (!*fd || **fd < 0)
148✔
167
                return;
168

169
        (void) fcntl_lock(**fd, LOCK_UN, /*ofd=*/ false);
148✔
170
        *fd = NULL;
148✔
171
}
172

UNCOV
173
void unposix_unlockpp(int **fd) {
×
UNCOV
174
        assert(fd);
×
175

176
        if (!*fd || **fd < 0)
×
177
                return;
178

UNCOV
179
        (void) fcntl_lock(**fd, LOCK_UN, /*ofd=*/ true);
×
UNCOV
180
        *fd = NULL;
×
181
}
182

183
int lock_generic(int fd, LockType type, int operation) {
298,143✔
184
        assert(fd >= 0);
298,143✔
185

186
        switch (type) {
298,143✔
187
        case LOCK_NONE:
188
                return 0;
189
        case LOCK_BSD:
3,021✔
190
                return RET_NERRNO(flock(fd, operation));
3,021✔
191
        case LOCK_POSIX:
1✔
192
                return posix_lock(fd, operation);
1✔
193
        case LOCK_UNPOSIX:
260,675✔
194
                return unposix_lock(fd, operation);
260,675✔
UNCOV
195
        default:
×
UNCOV
196
                assert_not_reached();
×
197
        }
198
}
199

200
int lock_generic_with_timeout(int fd, LockType type, int operation, usec_t timeout) {
475✔
201
        _cleanup_(sigkill_waitp) pid_t pid = 0;
475✔
202
        int r;
475✔
203

204
        assert(fd >= 0);
475✔
205

206
        /* A version of lock_generic(), but with a timeout. We do this in a child process, since the kernel
207
         * APIs natively don't support a timeout. We set a SIGALRM timer that will kill the child after the
208
         * timeout is hit. Returns -ETIMEDOUT if the timeout is hit, and 0 on success.
209
         *
210
         * This only works for BSD and UNPOSIX locks, as only those are fd-bound, and hence can be acquired
211
         * from any process that has access to the fd. POSIX locks OTOH are process-bound, and hence if we'd
212
         * acquire them in a child process they'd remain unlocked in the parent. */
213

214
        if (type == LOCK_NONE)
475✔
215
                return 0;
216
        if (!IN_SET(type, LOCK_BSD, LOCK_UNPOSIX)) /* Not for POSIX locks, see above. */
475✔
217
                return -EOPNOTSUPP;
218

219
        /* First, try without forking anything off */
220
        r = lock_generic(fd, type, operation | (timeout == USEC_INFINITY ? 0 : LOCK_NB));
950✔
221
        if (r != -EAGAIN || timeout == 0 || FLAGS_SET(operation, LOCK_NB))
475✔
222
                return r;
223

224
        /* If that didn't work, try with a child */
225

226
        r = safe_fork("(sd-flock)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, &pid);
464✔
227
        if (r < 0)
926✔
UNCOV
228
                return log_error_errno(r, "Failed to flock block device in child process: %m");
×
229
        if (r == 0) {
926✔
230
                struct sigevent sev = {
462✔
231
                        .sigev_notify = SIGEV_SIGNAL,
232
                        .sigev_signo = SIGALRM,
233
                };
234
                timer_t id;
462✔
235

236
                if (timer_create(CLOCK_MONOTONIC, &sev, &id) < 0) {
462✔
UNCOV
237
                        log_error_errno(errno, "Failed to allocate CLOCK_MONOTONIC timer: %m");
×
UNCOV
238
                        _exit(EXIT_FAILURE);
×
239
                }
240

241
                struct itimerspec its = {};
462✔
242
                timespec_store(&its.it_value, timeout);
462✔
243

244
                if (timer_settime(id, /* flags= */ 0, &its, NULL) < 0) {
462✔
UNCOV
245
                        log_error_errno(errno, "Failed to start CLOCK_MONOTONIC timer: %m");
×
UNCOV
246
                        _exit(EXIT_FAILURE);
×
247
                }
248

249
                if (lock_generic(fd, type, operation) < 0) {
462✔
UNCOV
250
                        log_error_errno(errno, "Unable to get an exclusive lock on the device: %m");
×
UNCOV
251
                        _exit(EXIT_FAILURE);
×
252
                }
253

254
                _exit(EXIT_SUCCESS);
462✔
255
        }
256

257
        siginfo_t status;
464✔
258
        r = wait_for_terminate(pid, &status);
464✔
259
        if (r < 0)
464✔
260
                return r;
261

262
        TAKE_PID(pid);
464✔
263

264
        switch (status.si_code) {
464✔
265

266
        case CLD_EXITED:
462✔
267
                if (status.si_status != EXIT_SUCCESS)
462✔
UNCOV
268
                        return -EPROTO;
×
269

270
                return 0;
271

272
        case CLD_KILLED:
2✔
273
                if (status.si_status == SIGALRM)
2✔
274
                        return -ETIMEDOUT;
2✔
275

276
                _fallthrough_;
277

278
        case CLD_DUMPED:
279
                return -EPROTO;
280

UNCOV
281
        default:
×
UNCOV
282
                assert_not_reached();
×
283
        }
284
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc