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

systemd / systemd / 14895667988

07 May 2025 08:57PM UTC coverage: 72.225% (-0.007%) from 72.232%
14895667988

push

github

yuwata
network: log_link_message_debug_errno() automatically append %m if necessary

Follow-up for d28746ef5.
Fixes CID#1609753.

0 of 1 new or added line in 1 file covered. (0.0%)

20297 existing lines in 338 files now uncovered.

297407 of 411780 relevant lines covered (72.22%)

695716.85 hits per line

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

67.13
/src/shared/loop-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#if HAVE_VALGRIND_MEMCHECK_H
4
#include <valgrind/memcheck.h>
5
#endif
6

7
#include <errno.h>
8
#include <fcntl.h>
9
#include <linux/blkpg.h>
10
#include <linux/loop.h>
11
#include <sys/file.h>
12
#include <sys/ioctl.h>
13
#include <unistd.h>
14

15
#include "sd-device.h"
16

17
#include "alloc-util.h"
18
#include "blockdev-util.h"
19
#include "data-fd-util.h"
20
#include "device-util.h"
21
#include "devnum-util.h"
22
#include "dissect-image.h"
23
#include "env-util.h"
24
#include "errno-util.h"
25
#include "fd-util.h"
26
#include "fileio.h"
27
#include "fs-util.h"
28
#include "loop-util.h"
29
#include "missing_fs.h"
30
#include "parse-util.h"
31
#include "path-util.h"
32
#include "random-util.h"
33
#include "stat-util.h"
34
#include "stdio-util.h"
35
#include "string-util.h"
36

37
static void cleanup_clear_loop_close(int *fd) {
1,903✔
38
        if (*fd < 0)
1,903✔
39
                return;
40

41
        (void) ioctl(*fd, LOOP_CLR_FD);
×
42
        (void) safe_close(*fd);
×
43
}
44

45
static int loop_is_bound(int fd) {
1,903✔
46
        struct loop_info64 info;
1,903✔
47

48
        if (ioctl(ASSERT_FD(fd), LOOP_GET_STATUS64, &info) < 0) {
1,903✔
49
                if (errno == ENXIO)
1,903✔
50
                        return false; /* not bound! */
51

52
                return -errno;
×
53
        }
54

55
        return true; /* bound! */
56
}
57

58
static int open_lock_fd(int primary_fd, int operation) {
2,019✔
59
        _cleanup_close_ int lock_fd = -EBADF;
2,019✔
60

61
        assert(IN_SET(operation & ~LOCK_NB, LOCK_SH, LOCK_EX));
2,019✔
62

63
        lock_fd = fd_reopen(ASSERT_FD(primary_fd), O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
2,019✔
64
        if (lock_fd < 0)
2,019✔
65
                return lock_fd;
66

67
        if (flock(lock_fd, operation) < 0)
2,019✔
68
                return -errno;
×
69

70
        return TAKE_FD(lock_fd);
71
}
72

73
static int loop_configure_verify_direct_io(int fd, const struct loop_config *c) {
1,903✔
74
        assert(fd >= 0);
1,903✔
75
        assert(c);
1,903✔
76

77
        if (FLAGS_SET(c->info.lo_flags, LO_FLAGS_DIRECT_IO)) {
1,903✔
78
                struct loop_info64 info;
1,902✔
79

80
                if (ioctl(fd, LOOP_GET_STATUS64, &info) < 0)
1,902✔
81
                        return log_debug_errno(errno, "Failed to issue LOOP_GET_STATUS64: %m");
×
82

83
#if HAVE_VALGRIND_MEMCHECK_H
84
                VALGRIND_MAKE_MEM_DEFINED(&info, sizeof(info));
85
#endif
86

87
                /* On older kernels (<= 5.3) it was necessary to set the block size of the loopback block
88
                 * device to the logical block size of the underlying file system. Since there was no nice
89
                 * way to query the value, we are not bothering to do this however. On newer kernels the
90
                 * block size is propagated automatically and does not require intervention from us. We'll
91
                 * check here if enabling direct IO worked, to make this easily debuggable however.
92
                 *
93
                 * (Should anyone really care and actually wants direct IO on old kernels: it might be worth
94
                 * enabling direct IO with iteratively larger block sizes until it eventually works.)
95
                 *
96
                 * On older kernels (e.g.: 5.10) when this is attempted on a file stored on a dm-crypt
97
                 * backed partition the kernel will start returning I/O errors when accessing the mounted
98
                 * loop device, so return a recognizable error that causes the operation to be started
99
                 * from scratch without the LO_FLAGS_DIRECT_IO flag. */
100
                if (!FLAGS_SET(info.lo_flags, LO_FLAGS_DIRECT_IO))
1,902✔
101
                        return log_debug_errno(
×
102
                                        SYNTHETIC_ERRNO(ENOANO),
103
                                        "Could not enable direct IO mode, retrying in buffered IO mode.");
104
        }
105

106
        return 0;
107
}
108

109
static int loop_configure_verify(int fd, const struct loop_config *c) {
1,903✔
110
        bool broken = false;
1,903✔
111
        int r;
1,903✔
112

113
        assert(fd >= 0);
1,903✔
114
        assert(c);
1,903✔
115

116
        if (c->block_size != 0) {
1,903✔
117
                uint32_t ssz;
1,903✔
118

119
                r = blockdev_get_sector_size(fd, &ssz);
1,903✔
120
                if (r < 0)
1,903✔
121
                        return r;
×
122

123
                if (ssz != c->block_size) {
1,903✔
124
                        log_debug("LOOP_CONFIGURE didn't honour requested block size %" PRIu32 ", got %" PRIu32 " instead. Ignoring.", c->block_size, ssz);
×
125
                        broken = true;
126
                }
127
        }
128

129
        if (c->info.lo_sizelimit != 0) {
1,903✔
130
                /* Kernel 5.8 vanilla doesn't properly propagate the size limit into the
131
                 * block device. If it's used, let's immediately check if it had the desired
132
                 * effect hence. And if not use classic LOOP_SET_STATUS64. */
133
                uint64_t z;
68✔
134

135
                r = blockdev_get_device_size(fd, &z);
68✔
136
                if (r < 0)
68✔
137
                        return r;
×
138

139
                if (z != c->info.lo_sizelimit) {
68✔
140
                        log_debug("LOOP_CONFIGURE is broken, doesn't honour .info.lo_sizelimit. Falling back to LOOP_SET_STATUS64.");
×
141
                        broken = true;
142
                }
143
        }
144

145
        if (FLAGS_SET(c->info.lo_flags, LO_FLAGS_PARTSCAN)) {
1,903✔
146
                /* Kernel 5.8 vanilla doesn't properly propagate the partition scanning flag
147
                 * into the block device. Let's hence verify if things work correctly here
148
                 * before returning. */
149

150
                r = blockdev_partscan_enabled_fd(fd);
1,761✔
151
                if (r < 0)
1,761✔
152
                        return r;
153
                if (r == 0) {
1,761✔
154
                        log_debug("LOOP_CONFIGURE is broken, doesn't honour LO_FLAGS_PARTSCAN. Falling back to LOOP_SET_STATUS64.");
×
155
                        broken = true;
156
                }
157
        }
158

159
        r = loop_configure_verify_direct_io(fd, c);
1,903✔
160
        if (r < 0)
1,903✔
161
                return r;
162

163
        return !broken;
1,903✔
164
}
165

166
static int loop_configure_fallback(int fd, const struct loop_config *c) {
×
167
        struct loop_info64 info_copy;
×
168
        int r;
×
169

170
        assert(fd >= 0);
×
171
        assert(c);
×
172

173
        /* Only some of the flags LOOP_CONFIGURE can set are also settable via LOOP_SET_STATUS64, hence mask
174
         * them out. */
175
        info_copy = c->info;
×
176
        info_copy.lo_flags &= LOOP_SET_STATUS_SETTABLE_FLAGS;
×
177

178
        /* Since kernel commit 5db470e229e22b7eda6e23b5566e532c96fb5bc3 (kernel v5.0) the LOOP_SET_STATUS64
179
         * ioctl can return EAGAIN in case we change the info.lo_offset field, if someone else is accessing the
180
         * block device while we try to reconfigure it. This is a pretty common case, since udev might
181
         * instantly start probing the device as soon as we attach an fd to it. Hence handle it in two ways:
182
         * first, let's take the BSD lock to ensure that udev will not step in between the point in
183
         * time where we attach the fd and where we reconfigure the device. Secondly, let's wait 50ms on
184
         * EAGAIN and retry. The former should be an efficient mechanism to avoid we have to wait 50ms
185
         * needlessly if we are just racing against udev. The latter is protection against all other cases,
186
         * i.e. peers that do not take the BSD lock. */
187

188
        for (unsigned n_attempts = 0;;) {
×
189
                if (ioctl(fd, LOOP_SET_STATUS64, &info_copy) >= 0)
×
190
                        break;
191

192
                if (errno != EAGAIN || ++n_attempts >= 64)
×
193
                        return log_debug_errno(errno, "Failed to configure loopback block device: %m");
×
194

195
                /* Sleep some random time, but at least 10ms, at most 250ms. Increase the delay the more
196
                 * failed attempts we see */
197
                (void) usleep_safe(UINT64_C(10) * USEC_PER_MSEC +
×
198
                              random_u64_range(UINT64_C(240) * USEC_PER_MSEC * n_attempts/64));
×
199
        }
200

201
        /* If a block size is requested then try to configure it. If that doesn't work, ignore errors, but
202
         * afterwards, let's validate what is in effect, and if it doesn't match what we want, fail */
203
        if (c->block_size != 0) {
×
204
                uint32_t ssz;
×
205

206
                if (ioctl(fd, LOOP_SET_BLOCK_SIZE, (unsigned long) c->block_size) < 0)
×
207
                        log_debug_errno(errno, "Failed to set sector size, ignoring: %m");
×
208

209
                r = blockdev_get_sector_size(fd, &ssz);
×
210
                if (r < 0)
×
211
                        return log_debug_errno(r, "Failed to read sector size: %m");
×
212
                if (ssz != c->block_size)
×
213
                        return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Sector size of loopback device doesn't match what we requested, refusing.");
×
214
        }
215

216
        /* LO_FLAGS_DIRECT_IO is a flags we need to configure via explicit ioctls. */
217
        if (FLAGS_SET(c->info.lo_flags, LO_FLAGS_DIRECT_IO))
×
218
                if (ioctl(fd, LOOP_SET_DIRECT_IO, 1UL) < 0)
×
219
                        log_debug_errno(errno, "Failed to enable direct IO mode, ignoring: %m");
×
220

221
        return loop_configure_verify_direct_io(fd, c);
×
222
}
223

224
static int loop_configure(
1,903✔
225
                int nr,
226
                int open_flags,
227
                int lock_op,
228
                const struct loop_config *c,
229
                LoopDevice **ret) {
230

231
        static bool loop_configure_broken = false;
1,903✔
232

233
        _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
1,903✔
234
        _cleanup_(cleanup_clear_loop_close) int loop_with_fd = -EBADF; /* This must be declared before lock_fd. */
×
235
        _cleanup_close_ int fd = -EBADF, lock_fd = -EBADF;
3,806✔
236
        _cleanup_free_ char *node = NULL;
1,903✔
237
        uint64_t diskseq = 0;
1,903✔
238
        dev_t devno;
1,903✔
239
        int r;
1,903✔
240

241
        assert(nr >= 0);
1,903✔
242
        assert(c);
1,903✔
243
        assert(ret);
1,903✔
244

245
        if (asprintf(&node, "/dev/loop%i", nr) < 0)
1,903✔
246
                return log_oom_debug();
×
247

248
        r = sd_device_new_from_devname(&dev, node);
1,903✔
249
        if (r < 0)
1,903✔
250
                return log_debug_errno(r, "Failed to create sd_device object for \"%s\": %m", node);
×
251

252
        r = sd_device_get_devnum(dev, &devno);
1,903✔
253
        if (r < 0)
1,903✔
254
                return log_device_debug_errno(dev, r, "Failed to get devnum: %m");
×
255

256
        fd = sd_device_open(dev, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|open_flags);
1,903✔
257
        if (fd < 0)
1,903✔
UNCOV
258
                return log_device_debug_errno(dev, fd, "Failed to open device: %m");
×
259

260
        /* Let's lock the device before we do anything. We take the BSD lock on a second, separately opened
261
         * fd for the device. udev after all watches for close() events (specifically IN_CLOSE_WRITE) on
262
         * block devices to reprobe them, hence by having a separate fd we will later close() we can ensure
263
         * we trigger udev after everything is done. If we'd lock our own fd instead and keep it open for a
264
         * long time udev would possibly never run on it again, even though the fd is unlocked, simply
265
         * because we never close() it. It also has the nice benefit we can use the _cleanup_close_ logic to
266
         * automatically release the lock, after we are done. */
267
        lock_fd = open_lock_fd(fd, LOCK_EX);
1,903✔
268
        if (lock_fd < 0)
1,903✔
269
                return log_device_debug_errno(dev, lock_fd, "Failed to acquire lock: %m");
×
270

271
        log_device_debug(dev, "Acquired exclusive lock.");
1,929✔
272

273
        /* Let's see if backing file is really unattached. Someone may already attach a backing file without
274
         * taking BSD lock. */
275
        r = loop_is_bound(fd);
1,903✔
276
        if (r < 0)
1,903✔
277
                return log_device_debug_errno(dev, r, "Failed to check if the loopback block device is bound: %m");
×
278
        if (r > 0)
1,903✔
279
                return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EBUSY),
×
280
                                              "The loopback block device is already bound, ignoring.");
281

282
        /* Let's see if the device is really detached, i.e. currently has no associated partition block
283
         * devices. On various kernels (such as 5.8) it is possible to have a loopback block device that
284
         * superficially is detached but still has partition block devices associated for it. Let's then
285
         * manually remove the partitions via BLKPG, and tell the caller we did that via EUCLEAN, so they try
286
         * again. */
287
        r = block_device_remove_all_partitions(dev, fd);
1,903✔
288
        if (r < 0)
1,903✔
289
                return log_device_debug_errno(dev, r, "Failed to remove partitions on the loopback block device: %m");
×
290
        if (r > 0)
1,903✔
291
                /* Removed all partitions. Let's report this to the caller, to try again, and count this as
292
                 * an attempt. */
293
                return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EUCLEAN),
×
294
                                              "Removed partitions on the loopback block device.");
295

296
        if (!loop_configure_broken) {
1,903✔
297
                if (ioctl(fd, LOOP_CONFIGURE, c) < 0) {
1,903✔
298
                        /* Do fallback only if LOOP_CONFIGURE is not supported, propagate all other errors. */
299
                        if (!ERRNO_IS_IOCTL_NOT_SUPPORTED(errno))
×
300
                                return log_device_debug_errno(dev, errno, "ioctl(LOOP_CONFIGURE) failed: %m");
×
301

302
                        loop_configure_broken = true;
×
303
                } else {
304
                        loop_with_fd = TAKE_FD(fd);
1,903✔
305

306
                        r = loop_configure_verify(loop_with_fd, c);
1,903✔
307
                        if (r < 0)
1,903✔
308
                                return log_device_debug_errno(dev, r, "Failed to verify if loopback block device is correctly configured: %m");
×
309
                        if (r == 0) {
1,903✔
310
                                /* LOOP_CONFIGURE doesn't work. Remember that. */
311
                                loop_configure_broken = true;
×
312

313
                                /* We return EBUSY here instead of retrying immediately with LOOP_SET_FD,
314
                                 * because LOOP_CLR_FD is async: if the operation cannot be executed right
315
                                 * away it just sets the autoclear flag on the device. This means there's a
316
                                 * good chance we cannot actually reuse the loopback device right-away. Hence
317
                                 * let's assume it's busy, avoid the trouble and let the calling loop call us
318
                                 * again with a new, likely unused device. */
319
                                return -EBUSY;
×
320
                        }
321
                }
322
        }
323

324
        if (loop_configure_broken) {
1,903✔
325
                if (ioctl(fd, LOOP_SET_FD, c->fd) < 0)
×
326
                        return log_device_debug_errno(dev, errno, "ioctl(LOOP_SET_FD) failed: %m");
×
327

328
                loop_with_fd = TAKE_FD(fd);
×
329

330
                r = loop_configure_fallback(loop_with_fd, c);
×
331
                if (r < 0)
×
332
                        return r;
333
        }
334

335
        r = fd_get_diskseq(loop_with_fd, &diskseq);
1,903✔
336
        if (r < 0 && r != -EOPNOTSUPP)
1,903✔
337
                return log_device_debug_errno(dev, r, "Failed to get diskseq: %m");
×
338

339
        switch (lock_op & ~LOCK_NB) {
1,903✔
340
        case LOCK_EX: /* Already in effect */
341
                break;
342
        case LOCK_SH: /* Downgrade */
1,801✔
343
                if (flock(lock_fd, lock_op) < 0)
1,801✔
344
                        return log_device_debug_errno(dev, errno, "Failed to downgrade lock level: %m");
×
345
                break;
346
        case LOCK_UN: /* Release */
×
347
                lock_fd = safe_close(lock_fd);
×
348
                break;
349
        default:
×
350
                assert_not_reached();
×
351
        }
352

353
        uint64_t device_size;
1,903✔
354
        r = blockdev_get_device_size(loop_with_fd, &device_size);
1,903✔
355
        if (r < 0)
1,903✔
356
                return log_device_debug_errno(dev, r, "Failed to get loopback device size: %m");
×
357

358
        LoopDevice *d = new(LoopDevice, 1);
1,903✔
359
        if (!d)
1,903✔
360
                return log_oom_debug();
×
361

362
        *d = (LoopDevice) {
1,903✔
363
                .n_ref = 1,
364
                .fd = TAKE_FD(loop_with_fd),
1,903✔
365
                .lock_fd = TAKE_FD(lock_fd),
1,903✔
366
                .node = TAKE_PTR(node),
1,903✔
367
                .nr = nr,
368
                .devno = devno,
369
                .dev = TAKE_PTR(dev),
1,903✔
370
                .diskseq = diskseq,
371
                .sector_size = c->block_size,
1,903✔
372
                .device_size = device_size,
373
                .created = true,
374
        };
375

376
        *ret = TAKE_PTR(d);
1,903✔
377
        return 0;
1,903✔
378
}
379

380
static int loop_device_make_internal(
4,051✔
381
                const char *path,
382
                int fd,
383
                int open_flags,
384
                uint64_t offset,
385
                uint64_t size,
386
                uint32_t sector_size,
387
                uint32_t loop_flags,
388
                int lock_op,
389
                LoopDevice **ret) {
390

391
        _cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
×
392
        _cleanup_close_ int reopened_fd = -EBADF, control = -EBADF;
8,102✔
393
        _cleanup_free_ char *backing_file = NULL;
4,051✔
394
        struct loop_config config;
4,051✔
395
        int r, f_flags;
4,051✔
396
        struct stat st;
4,051✔
397

398
        assert(ret);
4,051✔
399
        assert(IN_SET(open_flags, O_RDWR, O_RDONLY));
4,051✔
400

401
        if (fstat(ASSERT_FD(fd), &st) < 0)
4,051✔
402
                return -errno;
×
403

404
        if (S_ISBLK(st.st_mode)) {
4,051✔
405
                if (offset == 0 && IN_SET(size, 0, UINT64_MAX))
2✔
406
                        /* If this is already a block device and we are supposed to cover the whole of it
407
                         * then store an fd to the original open device node — and do not actually create an
408
                         * unnecessary loopback device for it. */
409
                        return loop_device_open_from_fd(fd, open_flags, lock_op, ret);
×
410
        } else {
411
                r = stat_verify_regular(&st);
4,049✔
412
                if (r < 0)
4,049✔
413
                        return r;
414
        }
415

416
        if (path) {
1,923✔
417
                r = path_make_absolute_cwd(path, &backing_file);
1,820✔
418
                if (r < 0)
1,820✔
419
                        return r;
420

421
                path_simplify(backing_file);
1,820✔
422
        } else {
423
                r = fd_get_path(fd, &backing_file);
103✔
424
                if (r < 0)
103✔
425
                        return r;
426
        }
427

428
        f_flags = fcntl(fd, F_GETFL);
1,923✔
429
        if (f_flags < 0)
1,923✔
430
                return -errno;
×
431

432
        if (FLAGS_SET(loop_flags, LO_FLAGS_DIRECT_IO) != FLAGS_SET(f_flags, O_DIRECT)) {
1,923✔
433
                /* If LO_FLAGS_DIRECT_IO is requested, then make sure we have the fd open with O_DIRECT, as
434
                 * that's required. Conversely, if it's off require that O_DIRECT is off too (that's because
435
                 * new kernels will implicitly enable LO_FLAGS_DIRECT_IO if O_DIRECT is set).
436
                 *
437
                 * Our intention here is that LO_FLAGS_DIRECT_IO is the primary knob, and O_DIRECT derived
438
                 * from that automatically. */
439

440
                reopened_fd = fd_reopen(fd, (FLAGS_SET(loop_flags, LO_FLAGS_DIRECT_IO) ? O_DIRECT : 0)|O_CLOEXEC|O_NONBLOCK|open_flags);
102✔
441
                if (reopened_fd < 0) {
102✔
442
                        if (!FLAGS_SET(loop_flags, LO_FLAGS_DIRECT_IO))
×
443
                                return log_debug_errno(reopened_fd, "Failed to reopen file descriptor without O_DIRECT: %m");
×
444

445
                        /* Some file systems might not support O_DIRECT, let's gracefully continue without it then. */
446
                        log_debug_errno(reopened_fd, "Failed to enable O_DIRECT for backing file descriptor for loopback device. Continuing without.");
×
447
                        loop_flags &= ~LO_FLAGS_DIRECT_IO;
×
448
                } else
449
                        fd = reopened_fd; /* From now on, operate on our new O_DIRECT fd */
450
        }
451

452
        control = open("/dev/loop-control", O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
1,923✔
453
        if (control < 0)
1,923✔
454
                return -errno;
20✔
455

456
        if (sector_size == 0)
1,903✔
457
                /* If no sector size is specified, default to the classic default */
458
                sector_size = 512;
×
459
        else if (sector_size == UINT32_MAX) {
1,903✔
460

461
                if (S_ISBLK(st.st_mode))
1,801✔
462
                        /* If the sector size is specified as UINT32_MAX we'll propagate the sector size of
463
                         * the underlying block device. */
464
                        r = blockdev_get_sector_size(fd, &sector_size);
×
465
                else {
466
                        _cleanup_close_ int non_direct_io_fd = -EBADF;
4,051✔
467
                        int probe_fd;
1,801✔
468

469
                        assert(S_ISREG(st.st_mode));
1,801✔
470

471
                        /* If sector size is specified as UINT32_MAX, we'll try to probe the right sector
472
                         * size of the image in question by looking for the GPT partition header at various
473
                         * offsets. This of course only works if the image already has a disk label.
474
                         *
475
                         * So here we actually want to read the file contents ourselves. This is quite likely
476
                         * not going to work if we managed to enable O_DIRECT, because in such a case there
477
                         * are some pretty strict alignment requirements to offset, size and target, but
478
                         * there's no way to query what alignment specifically is actually required. Hence,
479
                         * let's avoid the mess, and temporarily open an fd without O_DIRECT for the probing
480
                         * logic. */
481

482
                        if (FLAGS_SET(loop_flags, LO_FLAGS_DIRECT_IO)) {
1,801✔
483
                                non_direct_io_fd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
1,800✔
484
                                if (non_direct_io_fd < 0)
1,800✔
485
                                        return non_direct_io_fd;
×
486

487
                                probe_fd = non_direct_io_fd;
488
                        } else
489
                                probe_fd = fd;
490

491
                        r = probe_sector_size(probe_fd, &sector_size);
1,801✔
492
                }
493
                if (r < 0)
1,801✔
494
                        return r;
495
        }
496

497
        config = (struct loop_config) {
3,806✔
498
                .fd = fd,
499
                .block_size = sector_size,
500
                .info = {
501
                        /* Use the specified flags, but configure the read-only flag from the open flags, and force autoclear */
502
                        .lo_flags = (loop_flags & ~LO_FLAGS_READ_ONLY) | ((open_flags & O_ACCMODE_STRICT) == O_RDONLY ? LO_FLAGS_READ_ONLY : 0) | LO_FLAGS_AUTOCLEAR,
1,903✔
503
                        .lo_offset = offset,
504
                        .lo_sizelimit = size == UINT64_MAX ? 0 : size,
1,903✔
505
                },
506
        };
507

508
        /* Loop around LOOP_CTL_GET_FREE, since at the moment we attempt to open the returned device it might
509
         * be gone already, taken by somebody else racing against us. */
510
        for (unsigned n_attempts = 0;;) {
1,903✔
511
                usec_t usec;
1,903✔
512
                int nr;
1,903✔
513

514
                /* Let's take a lock on the control device first. On a busy system, where many programs
515
                 * attempt to allocate a loopback device at the same time, we might otherwise keep looping
516
                 * around relatively heavy operations: asking for a free loopback device, then opening it,
517
                 * validating it, attaching something to it. Let's serialize this whole operation, to make
518
                 * unnecessary busywork less likely. Note that this is just something we do to optimize our
519
                 * own code (and whoever else decides to use LOCK_EX locks for this), taking this lock is not
520
                 * necessary, it just means it's less likely we have to iterate through this loop again and
521
                 * again if our own code races against our own code.
522
                 *
523
                 * Note: our lock protocol is to take the /dev/loop-control lock first, and the block device
524
                 * lock second, if both are taken, and always in this order, to avoid ABBA locking issues. */
525
                if (flock(control, LOCK_EX) < 0)
1,903✔
526
                        return -errno;
×
527

528
                nr = ioctl(control, LOOP_CTL_GET_FREE);
1,903✔
529
                if (nr < 0)
1,903✔
530
                        return -errno;
×
531

532
                r = loop_configure(nr, open_flags, lock_op, &config, &d);
1,903✔
533
                if (r >= 0)
1,903✔
534
                        break;
535

536
                /* -ENODEV or friends: Somebody might've gotten the same number from the kernel, used the
537
                 * device, and called LOOP_CTL_REMOVE on it. Let's retry with a new number.
538
                 * -EBUSY: a file descriptor is already bound to the loopback block device.
539
                 * -EUCLEAN: some left-over partition devices that were cleaned up.
540
                 * -ENOANO: we tried to use LO_FLAGS_DIRECT_IO but the kernel rejected it. */
UNCOV
541
                if (!ERRNO_IS_DEVICE_ABSENT(r) && !IN_SET(r, -EBUSY, -EUCLEAN, -ENOANO))
×
542
                        return r;
543

544
                /* OK, this didn't work, let's try again a bit later, but first release the lock on the
545
                 * control device */
UNCOV
546
                if (flock(control, LOCK_UN) < 0)
×
547
                        return -errno;
×
548

UNCOV
549
                if (++n_attempts >= 64) /* Give up eventually */
×
550
                        return -EBUSY;
551

552
                /* If we failed to enable direct IO mode, let's retry without it. We restart the process as
553
                 * on some combination of kernel version and storage filesystem, the kernel is very unhappy
554
                 * about a failed DIRECT_IO enablement and throws I/O errors. */
UNCOV
555
                if (r == -ENOANO && FLAGS_SET(config.info.lo_flags, LO_FLAGS_DIRECT_IO)) {
×
556
                        config.info.lo_flags &= ~LO_FLAGS_DIRECT_IO;
×
557
                        open_flags &= ~O_DIRECT;
×
558

559
                        int non_direct_io_fd = fd_reopen(config.fd, O_CLOEXEC|O_NONBLOCK|open_flags);
×
560
                        if (non_direct_io_fd < 0)
×
561
                                return log_debug_errno(
×
562
                                                non_direct_io_fd,
563
                                                "Failed to reopen file descriptor without O_DIRECT: %m");
564

565
                        safe_close(reopened_fd);
×
566
                        fd = config.fd = /* For cleanups */ reopened_fd = non_direct_io_fd;
×
567
                }
568

569
                /* Wait some random time, to make collision less likely. Let's pick a random time in the
570
                 * range 0ms…250ms, linearly scaled by the number of failed attempts. */
UNCOV
571
                usec = random_u64_range(UINT64_C(10) * USEC_PER_MSEC +
×
UNCOV
572
                                        UINT64_C(240) * USEC_PER_MSEC * n_attempts/64);
×
UNCOV
573
                log_debug("Trying again after %s.", FORMAT_TIMESPAN(usec, USEC_PER_MSEC));
×
UNCOV
574
                (void) usleep_safe(usec);
×
575
        }
576

577
        d->backing_file = TAKE_PTR(backing_file);
1,903✔
578
        d->backing_inode = st.st_ino;
1,903✔
579
        d->backing_devno = st.st_dev;
1,903✔
580

581
        log_debug("Successfully acquired %s, devno=%u:%u, nr=%i, diskseq=%" PRIu64,
1,903✔
582
                  d->node,
583
                  major(d->devno), minor(d->devno),
584
                  d->nr,
585
                  d->diskseq);
586

587
        *ret = TAKE_PTR(d);
1,903✔
588
        return 0;
1,903✔
589
}
590

591
static uint32_t loop_flags_mangle(uint32_t loop_flags) {
4,051✔
592
        int r;
4,051✔
593

594
        r = getenv_bool("SYSTEMD_LOOP_DIRECT_IO");
4,051✔
595
        if (r < 0 && r != -ENXIO)
4,051✔
596
                log_debug_errno(r, "Failed to parse $SYSTEMD_LOOP_DIRECT_IO, ignoring: %m");
×
597

598
        return UPDATE_FLAG(loop_flags, LO_FLAGS_DIRECT_IO, r != 0); /* Turn on LO_FLAGS_DIRECT_IO by default, unless explicitly configured to off. */
4,051✔
599
}
600

601
int loop_device_make(
102✔
602
                int fd,
603
                int open_flags,
604
                uint64_t offset,
605
                uint64_t size,
606
                uint32_t sector_size,
607
                uint32_t loop_flags,
608
                int lock_op,
609
                LoopDevice **ret) {
610

611
        assert(fd >= 0);
102✔
612
        assert(ret);
102✔
613

614
        return loop_device_make_internal(
102✔
615
                        NULL,
616
                        fd,
617
                        open_flags,
618
                        offset,
619
                        size,
620
                        sector_size,
621
                        loop_flags_mangle(loop_flags),
622
                        lock_op,
623
                        ret);
624
}
625

626
int loop_device_make_by_path_at(
3,949✔
627
                int dir_fd,
628
                const char *path,
629
                int open_flags,
630
                uint32_t sector_size,
631
                uint32_t loop_flags,
632
                int lock_op,
633
                LoopDevice **ret) {
634

635
        int r, basic_flags, direct_flags, rdwr_flags;
3,949✔
636
        _cleanup_close_ int fd = -EBADF;
3,949✔
637
        bool direct = false;
3,949✔
638

639
        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
3,949✔
640
        assert(path);
3,949✔
641
        assert(ret);
3,949✔
642
        assert(open_flags < 0 || IN_SET(open_flags, O_RDWR, O_RDONLY));
3,949✔
643

644
        /* Passing < 0 as open_flags here means we'll try to open the device writable if we can, retrying
645
         * read-only if we cannot. */
646

647
        loop_flags = loop_flags_mangle(loop_flags);
3,949✔
648

649
        /* Let's open with O_DIRECT if we can. But not all file systems support that, hence fall back to
650
         * non-O_DIRECT mode automatically, if it fails. */
651

652
        basic_flags = O_CLOEXEC|O_NONBLOCK|O_NOCTTY;
3,949✔
653
        direct_flags = FLAGS_SET(loop_flags, LO_FLAGS_DIRECT_IO) ? O_DIRECT : 0;
3,949✔
654
        rdwr_flags = open_flags >= 0 ? open_flags : O_RDWR;
3,949✔
655

656
        fd = xopenat(dir_fd, path, basic_flags|direct_flags|rdwr_flags);
3,949✔
657
        if (fd < 0 && direct_flags != 0) /* If we had O_DIRECT on, and things failed with that, let's immediately try again without */
3,949✔
658
                fd = xopenat(dir_fd, path, basic_flags|rdwr_flags);
2,129✔
659
        else
660
                direct = direct_flags != 0;
×
661
        if (fd < 0) {
3,949✔
662
                r = fd;
1✔
663

664
                /* Retry read-only? */
665
                if (open_flags >= 0 || !(ERRNO_IS_PRIVILEGE(r) || r == -EROFS))
1✔
666
                        return r;
667

668
                fd = xopenat(dir_fd, path, basic_flags|direct_flags|O_RDONLY);
×
669
                if (fd < 0 && direct_flags != 0) /* as above */
×
670
                        fd = xopenat(dir_fd, path, basic_flags|O_RDONLY);
×
671
                else
672
                        direct = direct_flags != 0;
×
673
                if (fd < 0)
×
674
                        return r; /* Propagate original error */
675

676
                open_flags = O_RDONLY;
677
        } else if (open_flags < 0)
3,948✔
678
                open_flags = O_RDWR;
75✔
679

680
        log_debug("Opened '%s' in %s access mode%s, with O_DIRECT %s%s.",
15,614✔
681
                  path,
682
                  open_flags == O_RDWR ? "O_RDWR" : "O_RDONLY",
683
                  open_flags != rdwr_flags ? " (O_RDWR was requested but not allowed)" : "",
684
                  direct ? "enabled" : "disabled",
685
                  direct != (direct_flags != 0) ? " (O_DIRECT was requested but not supported)" : "");
686

687
        return loop_device_make_internal(
3,948✔
688
                        dir_fd == AT_FDCWD ? path : NULL,
689
                        fd,
690
                        open_flags,
691
                        /* offset = */ 0,
692
                        /* size = */ 0,
693
                        sector_size,
694
                        loop_flags,
695
                        lock_op,
696
                        ret);
697
}
698

699
int loop_device_make_by_path_memory(
1✔
700
                const char *path,
701
                int open_flags,
702
                uint32_t sector_size,
703
                uint32_t loop_flags,
704
                int lock_op,
705
                LoopDevice **ret) {
706

707
        _cleanup_close_ int fd = -EBADF, mfd = -EBADF;
1✔
708
        _cleanup_free_ char *fn = NULL;
1✔
709
        struct stat st;
1✔
710
        int r;
1✔
711

712
        assert(path);
1✔
713
        assert(IN_SET(open_flags, O_RDWR, O_RDONLY));
1✔
714
        assert(ret);
1✔
715

716
        loop_flags &= ~LO_FLAGS_DIRECT_IO; /* memfds don't support O_DIRECT, hence LO_FLAGS_DIRECT_IO can't be used either */
1✔
717

718
        fd = open(path, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|O_RDONLY);
1✔
719
        if (fd < 0)
1✔
720
                return -errno;
×
721

722
        if (fstat(fd, &st) < 0)
1✔
723
                return -errno;
×
724

725
        if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode))
1✔
726
                return -EBADF;
727

728
        r = path_extract_filename(path, &fn);
1✔
729
        if (r < 0)
1✔
730
                return r;
731

732
        mfd = memfd_clone_fd(fd, fn, open_flags|O_CLOEXEC);
1✔
733
        if (mfd < 0)
1✔
734
                return mfd;
735

736
        fd = safe_close(fd); /* Let's close the original early */
1✔
737

738
        return loop_device_make_internal(NULL, mfd, open_flags, 0, 0, sector_size, loop_flags, lock_op, ret);
1✔
739
}
740

741
static LoopDevice* loop_device_free(LoopDevice *d) {
1,937✔
742
        _cleanup_close_ int control = -EBADF;
1,937✔
743
        int r;
1,937✔
744

745
        if (!d)
1,937✔
746
                return NULL;
747

748
        /* Release any lock we might have on the device first. We want to open+lock the /dev/loop-control
749
         * device below, but our lock protocol says that if both control and block device locks are taken,
750
         * the control lock needs to be taken first, the block device lock second — in order to avoid ABBA
751
         * locking issues. Moreover, we want to issue LOOP_CLR_FD on the block device further down, and that
752
         * would fail if we had another fd open to the device. */
753
        d->lock_fd = safe_close(d->lock_fd);
1,937✔
754

755
        /* Let's open the control device early, and lock it, so that we can release our block device and
756
         * delete it in a synchronized fashion, and allocators won't needlessly see the block device as free
757
         * while we are about to delete it. */
758
        if (!LOOP_DEVICE_IS_FOREIGN(d) && !d->relinquished) {
1,937✔
759
                control = open("/dev/loop-control", O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
1,699✔
760
                if (control < 0)
1,699✔
761
                        log_debug_errno(errno, "Failed to open loop control device, cannot remove loop device '%s', ignoring: %m", strna(d->node));
×
762
                else if (flock(control, LOCK_EX) < 0)
1,699✔
763
                        log_debug_errno(errno, "Failed to lock loop control device, ignoring: %m");
×
764
        }
765

766
        /* Then let's release the loopback block device */
767
        if (d->fd >= 0) {
1,937✔
768
                /* Implicitly sync the device, since otherwise in-flight blocks might not get written */
769
                if (fsync(d->fd) < 0)
1,937✔
770
                        log_debug_errno(errno, "Failed to sync loop block device, ignoring: %m");
×
771

772
                if (!LOOP_DEVICE_IS_FOREIGN(d) && !d->relinquished) {
1,937✔
773
                        /* We are supposed to clear the loopback device. Let's do this synchronously: lock
774
                         * the device, manually remove all partitions and then clear it. This should ensure
775
                         * udev doesn't concurrently access the devices, and we can be reasonably sure that
776
                         * once we are done here the device is cleared and all its partition children
777
                         * removed. Note that we lock our primary device fd here (and not a separate locking
778
                         * fd, as we do during allocation, since we want to keep the lock all the way through
779
                         * the LOOP_CLR_FD, but that call would fail if we had more than one fd open.) */
780

781
                        if (flock(d->fd, LOCK_EX) < 0)
1,699✔
782
                                log_debug_errno(errno, "Failed to lock loop block device, ignoring: %m");
×
783

784
                        r = block_device_remove_all_partitions(d->dev, d->fd);
1,699✔
785
                        if (r < 0)
1,699✔
786
                                log_debug_errno(r, "Failed to remove partitions of loopback block device, ignoring: %m");
×
787

788
                        if (ioctl(d->fd, LOOP_CLR_FD) < 0)
1,699✔
789
                                log_debug_errno(errno, "Failed to clear loop device, ignoring: %m");
×
790
                }
791

792
                safe_close(d->fd);
1,937✔
793
        }
794

795
        /* Now that the block device is released, let's also try to remove it */
796
        if (control >= 0) {
1,937✔
797
                useconds_t delay = 5 * USEC_PER_MSEC;  /* A total delay of 5090 ms between 39 attempts,
798
                                                        * (4*5 + 5*10 + 5*20 + … + 3*640) = 5090. */
799

800
                for (unsigned attempt = 1;; attempt++) {
254✔
801
                        if (ioctl(control, LOOP_CTL_REMOVE, d->nr) >= 0)
1,953✔
802
                                break;
803
                        if (errno != EBUSY || attempt > 38) {
254✔
804
                                log_debug_errno(errno, "Failed to remove device %s: %m", strna(d->node));
×
805
                                break;
806
                        }
807
                        if (attempt % 5 == 0) {
254✔
808
                                log_debug("Device is still busy after %u attempts…", attempt);
8✔
809
                                delay *= 2;
8✔
810
                        }
811

812
                        (void) usleep_safe(delay);
254✔
813
                }
814
        }
815

816
        free(d->node);
1,937✔
817
        sd_device_unref(d->dev);
1,937✔
818
        free(d->backing_file);
1,937✔
819
        return mfree(d);
1,937✔
820
}
821

822
DEFINE_TRIVIAL_REF_UNREF_FUNC(LoopDevice, loop_device, loop_device_free);
5,967✔
823

824
void loop_device_relinquish(LoopDevice *d) {
143✔
825
        assert(d);
143✔
826

827
        /* Don't attempt to clean up the loop device anymore from this point on. Leave the clean-ing up to the kernel
828
         * itself, using the loop device "auto-clear" logic we already turned on when creating the device. */
829

830
        d->relinquished = true;
143✔
831
}
143✔
832

833
void loop_device_unrelinquish(LoopDevice *d) {
20✔
834
        assert(d);
20✔
835
        d->relinquished = false;
20✔
836
}
20✔
837

838
int loop_device_open(
115✔
839
                sd_device *dev,
840
                int open_flags,
841
                int lock_op,
842
                LoopDevice **ret) {
843

844
        _cleanup_close_ int fd = -EBADF, lock_fd = -EBADF;
115✔
845
        _cleanup_free_ char *node = NULL, *backing_file = NULL;
115✔
846
        dev_t devnum, backing_devno = 0;
115✔
847
        struct loop_info64 info;
115✔
848
        ino_t backing_inode = 0;
115✔
849
        uint64_t diskseq = 0;
115✔
850
        LoopDevice *d;
115✔
851
        const char *s;
115✔
852
        int r, nr = -1;
115✔
853

854
        assert(dev);
115✔
855
        assert(IN_SET(open_flags, O_RDWR, O_RDONLY));
115✔
856
        assert(ret);
115✔
857

858
        /* Even if fd is provided through the argument in loop_device_open_from_fd(), we reopen the inode
859
         * here, instead of keeping just a dup() clone of it around, since we want to ensure that the
860
         * O_DIRECT flag of the handle we keep is off, we have our own file index, and have the right
861
         * read/write mode in effect. */
862
        fd = sd_device_open(dev, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|open_flags);
115✔
863
        if (fd < 0)
115✔
864
                return fd;
865

866
        if ((lock_op & ~LOCK_NB) != LOCK_UN) {
115✔
867
                lock_fd = open_lock_fd(fd, lock_op);
115✔
868
                if (lock_fd < 0)
115✔
869
                        return lock_fd;
870
        }
871

872
        if (ioctl(fd, LOOP_GET_STATUS64, &info) >= 0) {
115✔
873
#if HAVE_VALGRIND_MEMCHECK_H
874
                /* Valgrind currently doesn't know LOOP_GET_STATUS64. Remove this once it does */
875
                VALGRIND_MAKE_MEM_DEFINED(&info, sizeof(info));
876
#endif
877
                nr = info.lo_number;
23✔
878

879
                if (sd_device_get_sysattr_value(dev, "loop/backing_file", &s) >= 0) {
23✔
880
                        backing_file = strdup(s);
13✔
881
                        if (!backing_file)
13✔
882
                                return -ENOMEM;
883
                }
884

885
                backing_devno = info.lo_device;
23✔
886
                backing_inode = info.lo_inode;
23✔
887
        }
888

889
        r = fd_get_diskseq(fd, &diskseq);
115✔
890
        if (r < 0 && r != -EOPNOTSUPP)
115✔
891
                return r;
892

893
        uint32_t sector_size;
115✔
894
        r = blockdev_get_sector_size(fd, &sector_size);
115✔
895
        if (r < 0)
115✔
896
                return r;
897

898
        uint64_t device_size;
115✔
899
        r = blockdev_get_device_size(fd, &device_size);
115✔
900
        if (r < 0)
115✔
901
                return r;
902

903
        r = sd_device_get_devnum(dev, &devnum);
115✔
904
        if (r < 0)
115✔
905
                return r;
906

907
        r = sd_device_get_devname(dev, &s);
115✔
908
        if (r < 0)
115✔
909
                return r;
910

911
        node = strdup(s);
115✔
912
        if (!node)
115✔
913
                return -ENOMEM;
914

915
        d = new(LoopDevice, 1);
115✔
916
        if (!d)
115✔
917
                return -ENOMEM;
918

919
        *d = (LoopDevice) {
230✔
920
                .n_ref = 1,
921
                .fd = TAKE_FD(fd),
115✔
922
                .lock_fd = TAKE_FD(lock_fd),
115✔
923
                .nr = nr,
924
                .node = TAKE_PTR(node),
115✔
925
                .dev = sd_device_ref(dev),
115✔
926
                .backing_file = TAKE_PTR(backing_file),
115✔
927
                .backing_inode = backing_inode,
928
                .backing_devno = backing_devno,
929
                .relinquished = true, /* It's not ours, don't try to destroy it when this object is freed */
930
                .devno = devnum,
931
                .diskseq = diskseq,
932
                .sector_size = sector_size,
933
                .device_size = device_size,
934
                .created = false,
935
        };
936

937
        *ret = d;
115✔
938
        return 0;
115✔
939
}
940

941
int loop_device_open_from_fd(
2✔
942
                int fd,
943
                int open_flags,
944
                int lock_op,
945
                LoopDevice **ret) {
946

947
        _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
2✔
948
        int r;
2✔
949

950
        r = block_device_new_from_fd(ASSERT_FD(fd), 0, &dev);
2✔
951
        if (r < 0)
2✔
952
                return r;
953

954
        return loop_device_open(dev, open_flags, lock_op, ret);
2✔
955
}
956

957
int loop_device_open_from_path(
×
958
                const char *path,
959
                int open_flags,
960
                int lock_op,
961
                LoopDevice **ret) {
962

963
        _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
×
964
        int r;
×
965

966
        assert(path);
×
967

968
        r = block_device_new_from_path(path, 0, &dev);
×
969
        if (r < 0)
×
970
                return r;
971

972
        return loop_device_open(dev, open_flags, lock_op, ret);
×
973
}
974

975
static int resize_partition(int partition_fd, uint64_t offset, uint64_t size) {
×
976
        char sysfs[STRLEN("/sys/dev/block/:/partition") + 2*DECIMAL_STR_MAX(dev_t) + 1];
×
977
        _cleanup_free_ char *buffer = NULL;
×
978
        uint64_t current_offset, current_size, partno;
×
979
        _cleanup_close_ int whole_fd = -EBADF;
×
980
        struct stat st;
×
981
        dev_t devno;
×
982
        int r;
×
983

984
        /* Resizes the partition the loopback device refer to (assuming it refers to one instead of an actual
985
         * loopback device), and changes the offset, if needed. This is a fancy wrapper around
986
         * BLKPG_RESIZE_PARTITION. */
987

988
        if (fstat(ASSERT_FD(partition_fd), &st) < 0)
×
989
                return -errno;
×
990

991
        assert(S_ISBLK(st.st_mode));
×
992

993
        xsprintf(sysfs, "/sys/dev/block/" DEVNUM_FORMAT_STR "/partition", DEVNUM_FORMAT_VAL(st.st_rdev));
×
994
        r = read_one_line_file(sysfs, &buffer);
×
995
        if (r == -ENOENT) /* not a partition, cannot resize */
×
996
                return -ENOTTY;
997
        if (r < 0)
×
998
                return r;
999
        r = safe_atou64(buffer, &partno);
×
1000
        if (r < 0)
×
1001
                return r;
1002

1003
        xsprintf(sysfs, "/sys/dev/block/" DEVNUM_FORMAT_STR "/start", DEVNUM_FORMAT_VAL(st.st_rdev));
×
1004

1005
        buffer = mfree(buffer);
×
1006
        r = read_one_line_file(sysfs, &buffer);
×
1007
        if (r < 0)
×
1008
                return r;
1009
        r = safe_atou64(buffer, &current_offset);
×
1010
        if (r < 0)
×
1011
                return r;
1012
        if (current_offset > UINT64_MAX/512U)
×
1013
                return -EINVAL;
1014
        current_offset *= 512U;
×
1015

1016
        r = blockdev_get_device_size(partition_fd, &current_size);
×
1017
        if (r < 0)
×
1018
                return r;
1019

1020
        if (size == UINT64_MAX && offset == UINT64_MAX)
×
1021
                return 0;
1022
        if (current_size == size && current_offset == offset)
×
1023
                return 0;
1024

1025
        xsprintf(sysfs, "/sys/dev/block/" DEVNUM_FORMAT_STR "/../dev", DEVNUM_FORMAT_VAL(st.st_rdev));
×
1026

1027
        buffer = mfree(buffer);
×
1028
        r = read_one_line_file(sysfs, &buffer);
×
1029
        if (r < 0)
×
1030
                return r;
1031
        r = parse_devnum(buffer, &devno);
×
1032
        if (r < 0)
×
1033
                return r;
1034

1035
        whole_fd = r = device_open_from_devnum(S_IFBLK, devno, O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY, NULL);
×
1036
        if (r < 0)
×
1037
                return r;
1038

1039
        return block_device_resize_partition(
×
1040
                        whole_fd,
1041
                        partno,
1042
                        offset == UINT64_MAX ? current_offset : offset,
1043
                        size == UINT64_MAX ? current_size : size);
1044
}
1045

1046
int loop_device_refresh_size(LoopDevice *d, uint64_t offset, uint64_t size) {
6✔
1047
        struct loop_info64 info;
6✔
1048

1049
        assert(d);
6✔
1050
        assert(d->fd >= 0);
6✔
1051

1052
        /* Changes the offset/start of the loop device relative to the beginning of the underlying file or
1053
         * block device. If this loop device actually refers to a partition and not a loopback device, we'll
1054
         * try to adjust the partition offsets instead.
1055
         *
1056
         * If either offset or size is UINT64_MAX we won't change that parameter. */
1057

1058
        if (d->nr < 0) /* not a loopback device */
6✔
1059
                return resize_partition(d->fd, offset, size);
×
1060

1061
        if (ioctl(d->fd, LOOP_GET_STATUS64, &info) < 0)
6✔
1062
                return -errno;
×
1063

1064
#if HAVE_VALGRIND_MEMCHECK_H
1065
        /* Valgrind currently doesn't know LOOP_GET_STATUS64. Remove this once it does */
1066
        VALGRIND_MAKE_MEM_DEFINED(&info, sizeof(info));
1067
#endif
1068

1069
        if (size == UINT64_MAX && offset == UINT64_MAX)
6✔
1070
                return 0;
1071
        if (info.lo_sizelimit == size && info.lo_offset == offset)
6✔
1072
                return 0;
1073

1074
        if (size != UINT64_MAX)
6✔
1075
                info.lo_sizelimit = size;
6✔
1076
        if (offset != UINT64_MAX)
6✔
1077
                info.lo_offset = offset;
×
1078

1079
        return RET_NERRNO(ioctl(d->fd, LOOP_SET_STATUS64, &info));
6✔
1080
}
1081

1082
int loop_device_flock(LoopDevice *d, int operation) {
130✔
1083
        assert(IN_SET(operation & ~LOCK_NB, LOCK_UN, LOCK_SH, LOCK_EX));
130✔
1084
        assert(d);
130✔
1085

1086
        /* When unlocking just close the lock fd */
1087
        if ((operation & ~LOCK_NB) == LOCK_UN) {
130✔
1088
                d->lock_fd = safe_close(d->lock_fd);
128✔
1089
                return 0;
128✔
1090
        }
1091

1092
        /* If we had no lock fd so far, create one and lock it right-away */
1093
        if (d->lock_fd < 0) {
2✔
1094
                d->lock_fd = open_lock_fd(ASSERT_FD(d->fd), operation);
1✔
1095
                if (d->lock_fd < 0)
1✔
1096
                        return d->lock_fd;
1097

1098
                return 0;
1✔
1099
        }
1100

1101
        /* Otherwise change the current lock mode on the existing fd */
1102
        return RET_NERRNO(flock(d->lock_fd, operation));
1✔
1103
}
1104

1105
int loop_device_sync(LoopDevice *d) {
56✔
1106
        assert(d);
56✔
1107

1108
        /* We also do this implicitly in loop_device_unref(). Doing this explicitly here has the benefit that
1109
         * we can check the return value though. */
1110

1111
        return RET_NERRNO(fsync(ASSERT_FD(d->fd)));
56✔
1112
}
1113

1114
int loop_device_set_autoclear(LoopDevice *d, bool autoclear) {
7✔
1115
        struct loop_info64 info;
7✔
1116

1117
        assert(d);
7✔
1118

1119
        if (ioctl(ASSERT_FD(d->fd), LOOP_GET_STATUS64, &info) < 0)
7✔
1120
                return -errno;
×
1121

1122
        if (autoclear == FLAGS_SET(info.lo_flags, LO_FLAGS_AUTOCLEAR))
7✔
1123
                return 0;
1124

1125
        SET_FLAG(info.lo_flags, LO_FLAGS_AUTOCLEAR, autoclear);
7✔
1126

1127
        if (ioctl(d->fd, LOOP_SET_STATUS64, &info) < 0)
7✔
1128
                return -errno;
×
1129

1130
        return 1;
1131
}
1132

1133
int loop_device_set_filename(LoopDevice *d, const char *name) {
3✔
1134
        struct loop_info64 info;
3✔
1135

1136
        assert(d);
3✔
1137

1138
        /* Sets the .lo_file_name of the loopback device. This is supposed to contain the path to the file
1139
         * backing the block device, but is actually just a free-form string you can pass to the kernel. Most
1140
         * tools that actually care for the backing file path use the sysfs attribute file loop/backing_file
1141
         * which is a kernel generated string, subject to file system namespaces and such.
1142
         *
1143
         * .lo_file_name is useful since userspace can select it freely when creating a loopback block
1144
         * device, and we can use it for /dev/disk/by-loop-ref/ symlinks, and similar, so that apps can
1145
         * recognize their own loopback files. */
1146

1147
        if (name && strlen(name) >= sizeof(info.lo_file_name))
3✔
1148
                return -ENOBUFS;
3✔
1149

1150
        if (ioctl(ASSERT_FD(d->fd), LOOP_GET_STATUS64, &info) < 0)
3✔
1151
                return -errno;
×
1152

1153
        if (strneq((char*) info.lo_file_name, strempty(name), sizeof(info.lo_file_name)))
3✔
1154
                return 0;
1155

1156
        if (name) {
3✔
1157
                strncpy((char*) info.lo_file_name, name, sizeof(info.lo_file_name)-1);
3✔
1158
                info.lo_file_name[sizeof(info.lo_file_name)-1] = 0;
3✔
1159
        } else
1160
                memzero(info.lo_file_name, sizeof(info.lo_file_name));
×
1161

1162
        if (ioctl(d->fd, LOOP_SET_STATUS64, &info) < 0)
3✔
1163
                return -errno;
×
1164

1165
        return 1;
1166
}
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