1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <linux/blkpg.h>
11 #include "alloc-util.h"
12 #include "blockdev-util.h"
13 #include "btrfs-util.h"
14 #include "device-util.h"
15 #include "devnum-util.h"
16 #include "dirent-util.h"
17 #include "errno-util.h"
21 #include "missing_magic.h"
22 #include "parse-util.h"
24 static int fd_get_devnum(int fd
, BlockDeviceLookupFlag flags
, dev_t
*ret
) {
32 if (fstat(fd
, &st
) < 0)
35 if (S_ISBLK(st
.st_mode
))
37 else if (!FLAGS_SET(flags
, BLOCK_DEVICE_LOOKUP_BACKING
))
39 else if (!S_ISREG(st
.st_mode
) && !S_ISDIR(st
.st_mode
))
41 else if (major(st
.st_dev
) != 0)
44 /* If major(st.st_dev) is zero, this might mean we are backed by btrfs, which needs special
45 * handing, to get the backing device node. */
47 r
= btrfs_get_block_device_fd(fd
, &devnum
);
48 if (r
== -ENOTTY
) /* not btrfs */
58 int block_device_is_whole_disk(sd_device
*dev
) {
64 r
= sd_device_get_subsystem(dev
, &s
);
68 if (!streq(s
, "block"))
71 r
= sd_device_get_devtype(dev
, &s
);
75 return streq(s
, "disk");
78 int block_device_get_whole_disk(sd_device
*dev
, sd_device
**ret
) {
84 /* Do not unref returned sd_device object. */
86 r
= block_device_is_whole_disk(dev
);
90 r
= sd_device_get_parent(dev
, &dev
);
91 if (r
== -ENOENT
) /* Already removed? Let's return a recognizable error. */
96 r
= block_device_is_whole_disk(dev
);
107 static int block_device_get_originating(sd_device
*dev
, sd_device
**ret
) {
108 _cleanup_(sd_device_unrefp
) sd_device
*first_found
= NULL
;
110 dev_t devnum
= 0; /* avoid false maybe-uninitialized warning */
112 /* For the specified block device tries to chase it through the layers, in case LUKS-style DM
113 * stacking is used, trying to find the next underlying layer. */
118 FOREACH_DEVICE_CHILD_WITH_SUFFIX(dev
, child
, suffix
) {
119 sd_device
*child_whole_disk
;
122 if (!path_startswith(suffix
, "slaves"))
125 if (block_device_get_whole_disk(child
, &child_whole_disk
) < 0)
128 if (sd_device_get_devnum(child_whole_disk
, &n
) < 0)
132 first_found
= sd_device_ref(child
);
137 /* We found a device backed by multiple other devices. We don't really support automatic
138 * discovery on such setups, with the exception of dm-verity partitions. In this case there
139 * are two backing devices: the data partition and the hash partition. We are fine with such
140 * setups, however, only if both partitions are on the same physical device. Hence, let's
141 * verify this by iterating over every node in the 'slaves/' directory and comparing them with
142 * the first that gets returned by readdir(), to ensure they all point to the same device. */
150 *ret
= TAKE_PTR(first_found
);
151 return 1; /* found */
154 int block_device_new_from_fd(int fd
, BlockDeviceLookupFlag flags
, sd_device
**ret
) {
155 _cleanup_(sd_device_unrefp
) sd_device
*dev
= NULL
;
162 r
= fd_get_devnum(fd
, flags
, &devnum
);
166 r
= sd_device_new_from_devnum(&dev
, 'b', devnum
);
170 if (FLAGS_SET(flags
, BLOCK_DEVICE_LOOKUP_ORIGINATING
)) {
171 _cleanup_(sd_device_unrefp
) sd_device
*dev_origin
= NULL
;
172 sd_device
*dev_whole_disk
;
174 r
= block_device_get_whole_disk(dev
, &dev_whole_disk
);
178 r
= block_device_get_originating(dev_whole_disk
, &dev_origin
);
179 if (r
< 0 && r
!= -ENOENT
)
182 device_unref_and_replace(dev
, dev_origin
);
185 if (FLAGS_SET(flags
, BLOCK_DEVICE_LOOKUP_WHOLE_DISK
)) {
186 sd_device
*dev_whole_disk
;
188 r
= block_device_get_whole_disk(dev
, &dev_whole_disk
);
192 *ret
= sd_device_ref(dev_whole_disk
);
196 *ret
= sd_device_ref(dev
);
200 int block_device_new_from_path(const char *path
, BlockDeviceLookupFlag flags
, sd_device
**ret
) {
201 _cleanup_close_
int fd
= -EBADF
;
206 fd
= open(path
, O_CLOEXEC
|O_PATH
);
210 return block_device_new_from_fd(fd
, flags
, ret
);
213 int block_get_whole_disk(dev_t d
, dev_t
*ret
) {
214 char p
[SYS_BLOCK_PATH_MAX("/partition")];
215 _cleanup_free_
char *s
= NULL
;
224 /* If it has a queue this is good enough for us */
225 xsprintf_sys_block_path(p
, "/queue", d
);
226 if (access(p
, F_OK
) >= 0) {
233 /* If it is a partition find the originating device */
234 xsprintf_sys_block_path(p
, "/partition", d
);
235 if (access(p
, F_OK
) < 0)
238 /* Get parent dev_t */
239 xsprintf_sys_block_path(p
, "/../dev", d
);
240 r
= read_one_line_file(p
, &s
);
244 r
= parse_devnum(s
, &devt
);
248 /* Only return this if it is really good enough for us. */
249 xsprintf_sys_block_path(p
, "/queue", devt
);
250 if (access(p
, F_OK
) < 0)
257 int get_block_device_fd(int fd
, dev_t
*ret
) {
264 /* Gets the block device directly backing a file system. If the block device is encrypted, returns
265 * the device mapper block device. */
270 if (major(st
.st_dev
) != 0) {
275 r
= btrfs_get_block_device_fd(fd
, ret
);
278 if (r
!= -ENOTTY
) /* not btrfs */
285 int get_block_device(const char *path
, dev_t
*ret
) {
286 _cleanup_close_
int fd
= -EBADF
;
291 fd
= open(path
, O_RDONLY
|O_NOFOLLOW
|O_CLOEXEC
);
295 return get_block_device_fd(fd
, ret
);
298 int block_get_originating(dev_t dt
, dev_t
*ret
) {
299 _cleanup_(sd_device_unrefp
) sd_device
*dev
= NULL
, *origin
= NULL
;
304 r
= sd_device_new_from_devnum(&dev
, 'b', dt
);
308 r
= block_device_get_originating(dev
, &origin
);
312 return sd_device_get_devnum(origin
, ret
);
315 int get_block_device_harder_fd(int fd
, dev_t
*ret
) {
321 /* Gets the backing block device for a file system, and handles LUKS encrypted file systems, looking for its
322 * immediate parent, if there is one. */
324 r
= get_block_device_fd(fd
, ret
);
328 r
= block_get_originating(*ret
, ret
);
330 log_debug_errno(r
, "Failed to chase block device, ignoring: %m");
335 int get_block_device_harder(const char *path
, dev_t
*ret
) {
336 _cleanup_close_
int fd
= -EBADF
;
341 fd
= open(path
, O_RDONLY
|O_NOFOLLOW
|O_CLOEXEC
);
345 return get_block_device_harder_fd(fd
, ret
);
348 int lock_whole_block_device(dev_t devt
, int operation
) {
349 _cleanup_close_
int lock_fd
= -EBADF
;
353 /* Let's get a BSD file lock on the whole block device, as per: https://systemd.io/BLOCK_DEVICE_LOCKING */
355 r
= block_get_whole_disk(devt
, &whole_devt
);
359 lock_fd
= r
= device_open_from_devnum(S_IFBLK
, whole_devt
, O_RDONLY
|O_CLOEXEC
|O_NONBLOCK
, NULL
);
363 if (flock(lock_fd
, operation
) < 0)
366 return TAKE_FD(lock_fd
);
369 int blockdev_partscan_enabled(int fd
) {
370 _cleanup_free_
char *p
= NULL
, *buf
= NULL
;
371 unsigned long long ull
;
375 /* Checks if partition scanning is correctly enabled on the block device */
377 if (fstat(fd
, &st
) < 0)
380 if (!S_ISBLK(st
.st_mode
))
383 if (asprintf(&p
, "/sys/dev/block/%u:%u/capability", major(st
.st_rdev
), minor(st
.st_rdev
)) < 0)
386 r
= read_one_line_file(p
, &buf
);
387 if (r
== -ENOENT
) /* If the capability file doesn't exist then we are most likely looking at a
388 * partition block device, not the whole block device. And that means we have no
389 * partition scanning on for it (we do for its parent, but not for the partition
395 r
= safe_atollu_full(buf
, 16, &ull
);
399 #ifndef GENHD_FL_NO_PART_SCAN
400 #define GENHD_FL_NO_PART_SCAN (0x0200)
403 return !FLAGS_SET(ull
, GENHD_FL_NO_PART_SCAN
);
406 static int blockdev_is_encrypted(const char *sysfs_path
, unsigned depth_left
) {
407 _cleanup_free_
char *p
= NULL
, *uuids
= NULL
;
408 _cleanup_closedir_
DIR *d
= NULL
;
409 int r
, found_encrypted
= false;
416 p
= path_join(sysfs_path
, "dm/uuid");
420 r
= read_one_line_file(p
, &uuids
);
425 /* The DM device's uuid attribute is prefixed with "CRYPT-" if this is a dm-crypt device. */
426 if (startswith(uuids
, "CRYPT-"))
430 /* Not a dm-crypt device itself. But maybe it is on top of one? Follow the links in the "slaves/"
434 p
= path_join(sysfs_path
, "slaves");
440 if (errno
== ENOENT
) /* Doesn't have underlying devices */
447 _cleanup_free_
char *q
= NULL
;
451 de
= readdir_no_dot(d
);
456 break; /* No more underlying devices */
459 q
= path_join(p
, de
->d_name
);
463 r
= blockdev_is_encrypted(q
, depth_left
- 1);
466 if (r
== 0) /* we found one that is not encrypted? then propagate that immediately */
469 found_encrypted
= true;
472 return found_encrypted
;
475 int fd_is_encrypted(int fd
) {
476 char p
[SYS_BLOCK_PATH_MAX(NULL
)];
480 r
= get_block_device_fd(fd
, &devt
);
483 if (r
== 0) /* doesn't have a block device */
486 xsprintf_sys_block_path(p
, NULL
, devt
);
488 return blockdev_is_encrypted(p
, 10 /* safety net: maximum recursion depth */);
491 int path_is_encrypted(const char *path
) {
492 char p
[SYS_BLOCK_PATH_MAX(NULL
)];
496 r
= get_block_device(path
, &devt
);
499 if (r
== 0) /* doesn't have a block device */
502 xsprintf_sys_block_path(p
, NULL
, devt
);
504 return blockdev_is_encrypted(p
, 10 /* safety net: maximum recursion depth */);
507 int fd_get_whole_disk(int fd
, bool backing
, dev_t
*ret
) {
514 r
= fd_get_devnum(fd
, backing
? BLOCK_DEVICE_LOOKUP_BACKING
: 0, &devt
);
518 return block_get_whole_disk(devt
, ret
);
521 int path_get_whole_disk(const char *path
, bool backing
, dev_t
*ret
) {
522 _cleanup_close_
int fd
= -EBADF
;
524 fd
= open(path
, O_CLOEXEC
|O_PATH
);
528 return fd_get_whole_disk(fd
, backing
, ret
);
531 int block_device_add_partition(
542 struct blkpg_partition bp
= {
548 struct blkpg_ioctl_arg ba
= {
549 .op
= BLKPG_ADD_PARTITION
,
551 .datalen
= sizeof(bp
),
554 if (strlen(name
) >= sizeof(bp
.devname
))
557 strcpy(bp
.devname
, name
);
559 return RET_NERRNO(ioctl(fd
, BLKPG
, &ba
));
562 int block_device_remove_partition(
571 struct blkpg_partition bp
= {
575 struct blkpg_ioctl_arg ba
= {
576 .op
= BLKPG_DEL_PARTITION
,
578 .datalen
= sizeof(bp
),
581 if (strlen(name
) >= sizeof(bp
.devname
))
584 strcpy(bp
.devname
, name
);
586 return RET_NERRNO(ioctl(fd
, BLKPG
, &ba
));
589 int block_device_resize_partition(
598 struct blkpg_partition bp
= {
604 struct blkpg_ioctl_arg ba
= {
605 .op
= BLKPG_RESIZE_PARTITION
,
607 .datalen
= sizeof(bp
),
610 return RET_NERRNO(ioctl(fd
, BLKPG
, &ba
));
613 int partition_enumerator_new(sd_device
*dev
, sd_device_enumerator
**ret
) {
614 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
621 /* Refuse invocation on partition block device, insist on "whole" device */
622 r
= block_device_is_whole_disk(dev
);
626 return -ENXIO
; /* return a recognizable error */
628 r
= sd_device_enumerator_new(&e
);
632 r
= sd_device_enumerator_allow_uninitialized(e
);
636 r
= sd_device_enumerator_add_match_parent(e
, dev
);
640 r
= sd_device_get_sysname(dev
, &s
);
644 /* Also add sysname check for safety. Hopefully, this also improves performance. */
645 s
= strjoina(s
, "*");
646 r
= sd_device_enumerator_add_match_sysname(e
, s
);
650 r
= sd_device_enumerator_add_match_subsystem(e
, "block", /* match = */ true);
654 r
= sd_device_enumerator_add_match_property(e
, "DEVTYPE", "partition");
662 int block_device_remove_all_partitions(sd_device
*dev
, int fd
) {
663 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
664 _cleanup_(sd_device_unrefp
) sd_device
*dev_unref
= NULL
;
665 _cleanup_close_
int fd_close
= -EBADF
;
666 bool has_partitions
= false;
669 assert(dev
|| fd
>= 0);
672 r
= block_device_new_from_fd(fd
, 0, &dev_unref
);
679 r
= partition_enumerator_new(dev
, &e
);
684 fd_close
= sd_device_open(dev
, O_CLOEXEC
|O_NONBLOCK
|O_NOCTTY
|O_RDONLY
);
691 FOREACH_DEVICE(e
, part
) {
692 const char *v
, *devname
;
695 has_partitions
= true;
697 r
= sd_device_get_devname(part
, &devname
);
701 r
= sd_device_get_property_value(part
, "PARTN", &v
);
705 r
= safe_atoi(v
, &nr
);
709 r
= btrfs_forget_device(devname
);
710 if (r
< 0 && r
!= -ENOENT
)
711 log_debug_errno(r
, "Failed to forget btrfs device %s, ignoring: %m", devname
);
713 r
= block_device_remove_partition(fd
, devname
, nr
);
715 log_debug("Kernel removed partition %s before us, ignoring", devname
);
719 log_debug_errno(r
, "Failed to remove partition %s: %m", devname
);
724 log_debug("Removed partition %s", devname
);
727 return k
< 0 ? k
: has_partitions
;
730 int block_device_has_partitions(sd_device
*dev
) {
731 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
736 /* Checks if the specified device currently has partitions. */
738 r
= partition_enumerator_new(dev
, &e
);
742 return !!sd_device_enumerator_get_device_first(e
);
745 int blockdev_reread_partition_table(sd_device
*dev
) {
746 _cleanup_close_
int fd
= -EBADF
;
750 /* Try to re-read the partition table. This only succeeds if none of the devices is busy. */
752 fd
= sd_device_open(dev
, O_RDONLY
|O_CLOEXEC
|O_NONBLOCK
|O_NOCTTY
);
756 if (flock(fd
, LOCK_EX
|LOCK_NB
) < 0)
759 if (ioctl(fd
, BLKRRPART
, 0) < 0)
765 int blockdev_get_sector_size(int fd
, uint32_t *ret
) {
771 if (ioctl(fd
, BLKSSZGET
, &ssz
) < 0)
773 if (ssz
<= 0) /* make sure the field is initialized */
774 return log_debug_errno(SYNTHETIC_ERRNO(EIO
), "Block device reported invalid sector size %i.", ssz
);
780 int blockdev_get_root(int level
, dev_t
*ret
) {
781 _cleanup_free_
char *p
= NULL
;
785 /* Returns the device node backing the root file system. Traces through
786 * dm-crypt/dm-verity/... Returns > 0 and the devno of the device on success. If there's no block
787 * device (or multiple) returns 0 and a devno of 0. Failure otherwise.
789 * If the root mount has been replaced by some form of volatile file system (overlayfs), the original
790 * root block device node is symlinked in /run/systemd/volatile-root. Let's read that here. */
791 r
= readlink_malloc("/run/systemd/volatile-root", &p
);
792 if (r
== -ENOENT
) { /* volatile-root not found */
793 r
= get_block_device_harder("/", &devno
);
795 return btrfs_log_dev_root(level
, r
, "root file system");
797 return log_full_errno(level
, r
, "Failed to determine block device of root file system: %m");
798 if (r
== 0) { /* Not backed by a single block device. (Could be NFS or so, or could be multi-device RAID or so) */
799 r
= get_block_device_harder("/usr", &devno
);
801 return btrfs_log_dev_root(level
, r
, "/usr");
803 return log_full_errno(level
, r
, "Failed to determine block device of /usr/ file system: %m");
804 if (r
== 0) { /* /usr/ not backed by single block device, either. */
805 log_debug("Neither root nor /usr/ file system are on a (single) block device.");
814 return log_full_errno(level
, r
, "Failed to read symlink /run/systemd/volatile-root: %m");
817 r
= device_path_parse_major_minor(p
, &m
, &devno
);
819 return log_full_errno(level
, r
, "Failed to parse major/minor device node: %m");
821 return log_full_errno(level
, SYNTHETIC_ERRNO(ENOTBLK
), "Volatile root device is of wrong type.");