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"
20 #include "missing_magic.h"
21 #include "parse-util.h"
23 int block_device_is_whole_disk(sd_device
*dev
) {
29 r
= sd_device_get_subsystem(dev
, &s
);
33 if (!streq(s
, "block"))
36 r
= sd_device_get_devtype(dev
, &s
);
40 return streq(s
, "disk");
43 int block_device_get_whole_disk(sd_device
*dev
, sd_device
**ret
) {
49 /* Do not unref returned sd_device object. */
51 r
= block_device_is_whole_disk(dev
);
55 r
= sd_device_get_parent(dev
, &dev
);
56 if (r
== -ENOENT
) /* Already removed? Let's return a recognizable error. */
61 r
= block_device_is_whole_disk(dev
);
72 int block_get_whole_disk(dev_t d
, dev_t
*ret
) {
73 char p
[SYS_BLOCK_PATH_MAX("/partition")];
74 _cleanup_free_
char *s
= NULL
;
83 /* If it has a queue this is good enough for us */
84 xsprintf_sys_block_path(p
, "/queue", d
);
85 if (access(p
, F_OK
) >= 0) {
92 /* If it is a partition find the originating device */
93 xsprintf_sys_block_path(p
, "/partition", d
);
94 if (access(p
, F_OK
) < 0)
97 /* Get parent dev_t */
98 xsprintf_sys_block_path(p
, "/../dev", d
);
99 r
= read_one_line_file(p
, &s
);
103 r
= parse_devnum(s
, &devt
);
107 /* Only return this if it is really good enough for us. */
108 xsprintf_sys_block_path(p
, "/queue", devt
);
109 if (access(p
, F_OK
) < 0)
116 int get_block_device_fd(int fd
, dev_t
*ret
) {
123 /* Gets the block device directly backing a file system. If the block device is encrypted, returns
124 * the device mapper block device. */
129 if (major(st
.st_dev
) != 0) {
134 r
= fcntl(fd
, F_GETFL
);
137 if (FLAGS_SET(r
, O_PATH
) && (S_ISREG(st
.st_mode
) || S_ISDIR(st
.st_mode
))) {
138 _cleanup_close_
int real_fd
= -1;
140 /* The fstat() above we can execute on an O_PATH fd. But the btrfs ioctl we cannot. Hence
141 * acquire a "real" fd first, without the O_PATH flag. */
143 real_fd
= fd_reopen(fd
, O_RDONLY
|O_CLOEXEC
);
146 r
= btrfs_get_block_device_fd(real_fd
, ret
);
148 r
= btrfs_get_block_device_fd(fd
, ret
);
151 if (r
!= -ENOTTY
) /* not btrfs */
158 int get_block_device(const char *path
, dev_t
*ret
) {
159 _cleanup_close_
int fd
= -1;
164 fd
= open(path
, O_RDONLY
|O_NOFOLLOW
|O_CLOEXEC
);
168 return get_block_device_fd(fd
, ret
);
171 int block_get_originating(dev_t dt
, dev_t
*ret
) {
172 _cleanup_closedir_
DIR *d
= NULL
;
173 _cleanup_free_
char *t
= NULL
;
174 char p
[SYS_BLOCK_PATH_MAX("/slaves")];
175 _cleanup_free_
char *first_found
= NULL
;
180 /* For the specified block device tries to chase it through the layers, in case LUKS-style DM stacking is used,
181 * trying to find the next underlying layer. */
183 xsprintf_sys_block_path(p
, "/slaves", dt
);
188 FOREACH_DIRENT_ALL(de
, d
, return -errno
) {
190 if (dot_or_dot_dot(de
->d_name
))
193 if (!IN_SET(de
->d_type
, DT_LNK
, DT_UNKNOWN
))
197 _cleanup_free_
char *u
= NULL
, *v
= NULL
, *a
= NULL
, *b
= NULL
;
199 /* We found a device backed by multiple other devices. We don't really support
200 * automatic discovery on such setups, with the exception of dm-verity partitions. In
201 * this case there are two backing devices: the data partition and the hash
202 * partition. We are fine with such setups, however, only if both partitions are on
203 * the same physical device. Hence, let's verify this by iterating over every node
204 * in the 'slaves/' directory and comparing them with the first that gets returned by
205 * readdir(), to ensure they all point to the same device. */
207 u
= path_join(p
, de
->d_name
, "../dev");
211 v
= path_join(p
, first_found
, "../dev");
215 r
= read_one_line_file(u
, &a
);
217 return log_debug_errno(r
, "Failed to read %s: %m", u
);
219 r
= read_one_line_file(v
, &b
);
221 return log_debug_errno(r
, "Failed to read %s: %m", v
);
223 /* Check if the parent device is the same. If not, then the two backing devices are on
224 * different physical devices, and we don't support that. */
228 first_found
= strdup(de
->d_name
);
237 q
= strjoina(p
, "/", first_found
, "/dev");
239 r
= read_one_line_file(q
, &t
);
243 r
= parse_devnum(t
, &devt
);
247 if (major(devt
) == 0)
254 int get_block_device_harder_fd(int fd
, dev_t
*ret
) {
260 /* Gets the backing block device for a file system, and handles LUKS encrypted file systems, looking for its
261 * immediate parent, if there is one. */
263 r
= get_block_device_fd(fd
, ret
);
267 r
= block_get_originating(*ret
, ret
);
269 log_debug_errno(r
, "Failed to chase block device, ignoring: %m");
274 int get_block_device_harder(const char *path
, dev_t
*ret
) {
275 _cleanup_close_
int fd
= -1;
280 fd
= open(path
, O_RDONLY
|O_NOFOLLOW
|O_CLOEXEC
);
284 return get_block_device_harder_fd(fd
, ret
);
287 int lock_whole_block_device(dev_t devt
, int operation
) {
288 _cleanup_close_
int lock_fd
= -1;
292 /* Let's get a BSD file lock on the whole block device, as per: https://systemd.io/BLOCK_DEVICE_LOCKING */
294 r
= block_get_whole_disk(devt
, &whole_devt
);
298 lock_fd
= r
= device_open_from_devnum(S_IFBLK
, whole_devt
, O_RDONLY
|O_CLOEXEC
|O_NONBLOCK
, NULL
);
302 if (flock(lock_fd
, operation
) < 0)
305 return TAKE_FD(lock_fd
);
308 int blockdev_partscan_enabled(int fd
) {
309 _cleanup_free_
char *p
= NULL
, *buf
= NULL
;
310 unsigned long long ull
;
314 /* Checks if partition scanning is correctly enabled on the block device */
316 if (fstat(fd
, &st
) < 0)
319 if (!S_ISBLK(st
.st_mode
))
322 if (asprintf(&p
, "/sys/dev/block/%u:%u/capability", major(st
.st_rdev
), minor(st
.st_rdev
)) < 0)
325 r
= read_one_line_file(p
, &buf
);
326 if (r
== -ENOENT
) /* If the capability file doesn't exist then we are most likely looking at a
327 * partition block device, not the whole block device. And that means we have no
328 * partition scanning on for it (we do for its parent, but not for the partition
334 r
= safe_atollu_full(buf
, 16, &ull
);
338 #ifndef GENHD_FL_NO_PART_SCAN
339 #define GENHD_FL_NO_PART_SCAN (0x0200)
342 return !FLAGS_SET(ull
, GENHD_FL_NO_PART_SCAN
);
345 static int blockdev_is_encrypted(const char *sysfs_path
, unsigned depth_left
) {
346 _cleanup_free_
char *p
= NULL
, *uuids
= NULL
;
347 _cleanup_closedir_
DIR *d
= NULL
;
348 int r
, found_encrypted
= false;
355 p
= path_join(sysfs_path
, "dm/uuid");
359 r
= read_one_line_file(p
, &uuids
);
364 /* The DM device's uuid attribute is prefixed with "CRYPT-" if this is a dm-crypt device. */
365 if (startswith(uuids
, "CRYPT-"))
369 /* Not a dm-crypt device itself. But maybe it is on top of one? Follow the links in the "slaves/"
373 p
= path_join(sysfs_path
, "slaves");
379 if (errno
== ENOENT
) /* Doesn't have underlying devices */
386 _cleanup_free_
char *q
= NULL
;
390 de
= readdir_no_dot(d
);
395 break; /* No more underlying devices */
398 q
= path_join(p
, de
->d_name
);
402 r
= blockdev_is_encrypted(q
, depth_left
- 1);
405 if (r
== 0) /* we found one that is not encrypted? then propagate that immediately */
408 found_encrypted
= true;
411 return found_encrypted
;
414 int fd_is_encrypted(int fd
) {
415 char p
[SYS_BLOCK_PATH_MAX(NULL
)];
419 r
= get_block_device_fd(fd
, &devt
);
422 if (r
== 0) /* doesn't have a block device */
425 xsprintf_sys_block_path(p
, NULL
, devt
);
427 return blockdev_is_encrypted(p
, 10 /* safety net: maximum recursion depth */);
430 int path_is_encrypted(const char *path
) {
431 char p
[SYS_BLOCK_PATH_MAX(NULL
)];
435 r
= get_block_device(path
, &devt
);
438 if (r
== 0) /* doesn't have a block device */
441 xsprintf_sys_block_path(p
, NULL
, devt
);
443 return blockdev_is_encrypted(p
, 10 /* safety net: maximum recursion depth */);
446 int fd_get_whole_disk(int fd
, bool backing
, dev_t
*ret
) {
453 if (fstat(fd
, &st
) < 0)
456 if (S_ISBLK(st
.st_mode
))
460 else if (!S_ISREG(st
.st_mode
) && !S_ISDIR(st
.st_mode
))
462 else if (major(st
.st_dev
) != 0)
465 _cleanup_close_
int regfd
= -1;
467 /* If major(st.st_dev) is zero, this might mean we are backed by btrfs, which needs special
468 * handing, to get the backing device node. */
470 regfd
= fd_reopen(fd
, O_RDONLY
|O_CLOEXEC
|O_NONBLOCK
);
474 r
= btrfs_get_block_device_fd(regfd
, &devt
);
481 return block_get_whole_disk(devt
, ret
);
484 int path_get_whole_disk(const char *path
, bool backing
, dev_t
*ret
) {
485 _cleanup_close_
int fd
= -1;
487 fd
= open(path
, O_CLOEXEC
|O_PATH
);
491 return fd_get_whole_disk(fd
, backing
, ret
);
494 int block_device_add_partition(
505 struct blkpg_partition bp
= {
511 struct blkpg_ioctl_arg ba
= {
512 .op
= BLKPG_ADD_PARTITION
,
514 .datalen
= sizeof(bp
),
517 if (strlen(name
) >= sizeof(bp
.devname
))
520 strcpy(bp
.devname
, name
);
522 return RET_NERRNO(ioctl(fd
, BLKPG
, &ba
));
525 int block_device_remove_partition(
534 struct blkpg_partition bp
= {
538 struct blkpg_ioctl_arg ba
= {
539 .op
= BLKPG_DEL_PARTITION
,
541 .datalen
= sizeof(bp
),
544 if (strlen(name
) >= sizeof(bp
.devname
))
547 strcpy(bp
.devname
, name
);
549 return RET_NERRNO(ioctl(fd
, BLKPG
, &ba
));
552 int block_device_resize_partition(
561 struct blkpg_partition bp
= {
567 struct blkpg_ioctl_arg ba
= {
568 .op
= BLKPG_RESIZE_PARTITION
,
570 .datalen
= sizeof(bp
),
573 return RET_NERRNO(ioctl(fd
, BLKPG
, &ba
));
576 int partition_enumerator_new(sd_device
*dev
, sd_device_enumerator
**ret
) {
577 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
584 /* Refuse invocation on partition block device, insist on "whole" device */
585 r
= block_device_is_whole_disk(dev
);
589 return -ENXIO
; /* return a recognizable error */
591 r
= sd_device_enumerator_new(&e
);
595 r
= sd_device_enumerator_allow_uninitialized(e
);
599 r
= sd_device_enumerator_add_match_parent(e
, dev
);
603 r
= sd_device_get_sysname(dev
, &s
);
607 /* Also add sysname check for safety. Hopefully, this also improves performance. */
608 s
= strjoina(s
, "*");
609 r
= sd_device_enumerator_add_match_sysname(e
, s
);
613 r
= sd_device_enumerator_add_match_subsystem(e
, "block", /* match = */ true);
617 r
= sd_device_enumerator_add_match_property(e
, "DEVTYPE", "partition");
625 int block_device_remove_all_partitions(sd_device
*dev
, int fd
) {
626 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
627 _cleanup_(sd_device_unrefp
) sd_device
*dev_unref
= NULL
;
628 _cleanup_close_
int fd_close
= -1;
629 bool has_partitions
= false;
633 assert(dev
|| fd
>= 0);
638 if (fstat(fd
, &st
) < 0)
641 r
= sd_device_new_from_stat_rdev(&dev_unref
, &st
);
648 r
= partition_enumerator_new(dev
, &e
);
653 fd_close
= sd_device_open(dev
, O_CLOEXEC
|O_NONBLOCK
|O_NOCTTY
|O_RDONLY
);
660 FOREACH_DEVICE(e
, part
) {
661 const char *v
, *devname
;
664 has_partitions
= true;
666 r
= sd_device_get_devname(part
, &devname
);
670 r
= sd_device_get_property_value(part
, "PARTN", &v
);
674 r
= safe_atoi(v
, &nr
);
678 r
= block_device_remove_partition(fd
, devname
, nr
);
680 log_debug("Kernel removed partition %s before us, ignoring", devname
);
684 log_debug_errno(r
, "Failed to remove partition %s: %m", devname
);
689 log_debug("Removed partition %s", devname
);
692 return k
< 0 ? k
: has_partitions
;
695 int block_device_has_partitions(sd_device
*dev
) {
696 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
701 /* Checks if the specified device currently has partitions. */
703 r
= partition_enumerator_new(dev
, &e
);
707 return !!sd_device_enumerator_get_device_first(e
);
710 int blockdev_reread_partition_table(sd_device
*dev
) {
711 _cleanup_close_
int fd
= -1;
715 /* Try to re-read the partition table. This only succeeds if none of the devices is busy. */
717 fd
= sd_device_open(dev
, O_RDONLY
|O_CLOEXEC
|O_NONBLOCK
|O_NOCTTY
);
721 if (flock(fd
, LOCK_EX
|LOCK_NB
) < 0)
724 if (ioctl(fd
, BLKRRPART
, 0) < 0)