]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/blockdev-util.c
device-util: Declare iterator variables inline
[thirdparty/systemd.git] / src / shared / blockdev-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <linux/blkpg.h>
4 #include <sys/file.h>
5 #include <sys/ioctl.h>
6 #include <sys/mount.h>
7 #include <unistd.h>
8
9 #include "sd-device.h"
10
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"
18 #include "fd-util.h"
19 #include "fileio.h"
20 #include "fs-util.h"
21 #include "missing_magic.h"
22 #include "parse-util.h"
23
24 static int fd_get_devnum(int fd, BlockDeviceLookupFlag flags, dev_t *ret) {
25 struct stat st;
26 dev_t devnum;
27 int r;
28
29 assert(fd >= 0);
30 assert(ret);
31
32 if (fstat(fd, &st) < 0)
33 return -errno;
34
35 if (S_ISBLK(st.st_mode))
36 devnum = st.st_rdev;
37 else if (!FLAGS_SET(flags, BLOCK_DEVICE_LOOKUP_BACKING))
38 return -ENOTBLK;
39 else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
40 return -ENOTBLK;
41 else if (major(st.st_dev) != 0)
42 devnum = st.st_dev;
43 else {
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. */
46
47 r = btrfs_get_block_device_fd(fd, &devnum);
48 if (r == -ENOTTY) /* not btrfs */
49 return -ENOTBLK;
50 if (r < 0)
51 return r;
52 }
53
54 *ret = devnum;
55 return 0;
56 }
57
58 int block_device_is_whole_disk(sd_device *dev) {
59 const char *s;
60 int r;
61
62 assert(dev);
63
64 r = sd_device_get_subsystem(dev, &s);
65 if (r < 0)
66 return r;
67
68 if (!streq(s, "block"))
69 return -ENOTBLK;
70
71 r = sd_device_get_devtype(dev, &s);
72 if (r < 0)
73 return r;
74
75 return streq(s, "disk");
76 }
77
78 int block_device_get_whole_disk(sd_device *dev, sd_device **ret) {
79 int r;
80
81 assert(dev);
82 assert(ret);
83
84 /* Do not unref returned sd_device object. */
85
86 r = block_device_is_whole_disk(dev);
87 if (r < 0)
88 return r;
89 if (r == 0) {
90 r = sd_device_get_parent(dev, &dev);
91 if (r == -ENOENT) /* Already removed? Let's return a recognizable error. */
92 return -ENODEV;
93 if (r < 0)
94 return r;
95
96 r = block_device_is_whole_disk(dev);
97 if (r < 0)
98 return r;
99 if (r == 0)
100 return -ENXIO;
101 }
102
103 *ret = dev;
104 return 0;
105 }
106
107 static int block_device_get_originating(sd_device *dev, sd_device **ret) {
108 _cleanup_(sd_device_unrefp) sd_device *first_found = NULL;
109 const char *suffix;
110 dev_t devnum = 0; /* avoid false maybe-uninitialized warning */
111
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. */
114
115 assert(dev);
116 assert(ret);
117
118 FOREACH_DEVICE_CHILD_WITH_SUFFIX(dev, child, suffix) {
119 sd_device *child_whole_disk;
120 dev_t n;
121
122 if (!path_startswith(suffix, "slaves"))
123 continue;
124
125 if (block_device_get_whole_disk(child, &child_whole_disk) < 0)
126 continue;
127
128 if (sd_device_get_devnum(child_whole_disk, &n) < 0)
129 continue;
130
131 if (!first_found) {
132 first_found = sd_device_ref(child);
133 devnum = n;
134 continue;
135 }
136
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. */
143 if (n != devnum)
144 return -ENOTUNIQ;
145 }
146
147 if (!first_found)
148 return -ENOENT;
149
150 *ret = TAKE_PTR(first_found);
151 return 1; /* found */
152 }
153
154 int block_device_new_from_fd(int fd, BlockDeviceLookupFlag flags, sd_device **ret) {
155 _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
156 dev_t devnum;
157 int r;
158
159 assert(fd >= 0);
160 assert(ret);
161
162 r = fd_get_devnum(fd, flags, &devnum);
163 if (r < 0)
164 return r;
165
166 r = sd_device_new_from_devnum(&dev, 'b', devnum);
167 if (r < 0)
168 return r;
169
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;
173
174 r = block_device_get_whole_disk(dev, &dev_whole_disk);
175 if (r < 0)
176 return r;
177
178 r = block_device_get_originating(dev_whole_disk, &dev_origin);
179 if (r < 0 && r != -ENOENT)
180 return r;
181 if (r > 0)
182 device_unref_and_replace(dev, dev_origin);
183 }
184
185 if (FLAGS_SET(flags, BLOCK_DEVICE_LOOKUP_WHOLE_DISK)) {
186 sd_device *dev_whole_disk;
187
188 r = block_device_get_whole_disk(dev, &dev_whole_disk);
189 if (r < 0)
190 return r;
191
192 *ret = sd_device_ref(dev_whole_disk);
193 return 0;
194 }
195
196 *ret = sd_device_ref(dev);
197 return 0;
198 }
199
200 int block_device_new_from_path(const char *path, BlockDeviceLookupFlag flags, sd_device **ret) {
201 _cleanup_close_ int fd = -EBADF;
202
203 assert(path);
204 assert(ret);
205
206 fd = open(path, O_CLOEXEC|O_PATH);
207 if (fd < 0)
208 return -errno;
209
210 return block_device_new_from_fd(fd, flags, ret);
211 }
212
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;
216 dev_t devt;
217 int r;
218
219 assert(ret);
220
221 if (major(d) == 0)
222 return -ENODEV;
223
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) {
227 *ret = d;
228 return 0;
229 }
230 if (errno != ENOENT)
231 return -errno;
232
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)
236 return -errno;
237
238 /* Get parent dev_t */
239 xsprintf_sys_block_path(p, "/../dev", d);
240 r = read_one_line_file(p, &s);
241 if (r < 0)
242 return r;
243
244 r = parse_devnum(s, &devt);
245 if (r < 0)
246 return r;
247
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)
251 return -errno;
252
253 *ret = devt;
254 return 1;
255 }
256
257 int get_block_device_fd(int fd, dev_t *ret) {
258 struct stat st;
259 int r;
260
261 assert(fd >= 0);
262 assert(ret);
263
264 /* Gets the block device directly backing a file system. If the block device is encrypted, returns
265 * the device mapper block device. */
266
267 if (fstat(fd, &st))
268 return -errno;
269
270 if (major(st.st_dev) != 0) {
271 *ret = st.st_dev;
272 return 1;
273 }
274
275 r = btrfs_get_block_device_fd(fd, ret);
276 if (r > 0)
277 return 1;
278 if (r != -ENOTTY) /* not btrfs */
279 return r;
280
281 *ret = 0;
282 return 0;
283 }
284
285 int get_block_device(const char *path, dev_t *ret) {
286 _cleanup_close_ int fd = -EBADF;
287
288 assert(path);
289 assert(ret);
290
291 fd = open(path, O_RDONLY|O_NOFOLLOW|O_CLOEXEC);
292 if (fd < 0)
293 return -errno;
294
295 return get_block_device_fd(fd, ret);
296 }
297
298 int block_get_originating(dev_t dt, dev_t *ret) {
299 _cleanup_(sd_device_unrefp) sd_device *dev = NULL, *origin = NULL;
300 int r;
301
302 assert(ret);
303
304 r = sd_device_new_from_devnum(&dev, 'b', dt);
305 if (r < 0)
306 return r;
307
308 r = block_device_get_originating(dev, &origin);
309 if (r < 0)
310 return r;
311
312 return sd_device_get_devnum(origin, ret);
313 }
314
315 int get_block_device_harder_fd(int fd, dev_t *ret) {
316 int r;
317
318 assert(fd >= 0);
319 assert(ret);
320
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. */
323
324 r = get_block_device_fd(fd, ret);
325 if (r <= 0)
326 return r;
327
328 r = block_get_originating(*ret, ret);
329 if (r < 0)
330 log_debug_errno(r, "Failed to chase block device, ignoring: %m");
331
332 return 1;
333 }
334
335 int get_block_device_harder(const char *path, dev_t *ret) {
336 _cleanup_close_ int fd = -EBADF;
337
338 assert(path);
339 assert(ret);
340
341 fd = open(path, O_RDONLY|O_NOFOLLOW|O_CLOEXEC);
342 if (fd < 0)
343 return -errno;
344
345 return get_block_device_harder_fd(fd, ret);
346 }
347
348 int lock_whole_block_device(dev_t devt, int operation) {
349 _cleanup_close_ int lock_fd = -EBADF;
350 dev_t whole_devt;
351 int r;
352
353 /* Let's get a BSD file lock on the whole block device, as per: https://systemd.io/BLOCK_DEVICE_LOCKING */
354
355 r = block_get_whole_disk(devt, &whole_devt);
356 if (r < 0)
357 return r;
358
359 lock_fd = r = device_open_from_devnum(S_IFBLK, whole_devt, O_RDONLY|O_CLOEXEC|O_NONBLOCK, NULL);
360 if (r < 0)
361 return r;
362
363 if (flock(lock_fd, operation) < 0)
364 return -errno;
365
366 return TAKE_FD(lock_fd);
367 }
368
369 int blockdev_partscan_enabled(int fd) {
370 _cleanup_free_ char *p = NULL, *buf = NULL;
371 unsigned long long ull;
372 struct stat st;
373 int r;
374
375 /* Checks if partition scanning is correctly enabled on the block device */
376
377 if (fstat(fd, &st) < 0)
378 return -errno;
379
380 if (!S_ISBLK(st.st_mode))
381 return -ENOTBLK;
382
383 if (asprintf(&p, "/sys/dev/block/%u:%u/capability", major(st.st_rdev), minor(st.st_rdev)) < 0)
384 return -ENOMEM;
385
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
390 * itself). */
391 return false;
392 if (r < 0)
393 return r;
394
395 r = safe_atollu_full(buf, 16, &ull);
396 if (r < 0)
397 return r;
398
399 #ifndef GENHD_FL_NO_PART_SCAN
400 #define GENHD_FL_NO_PART_SCAN (0x0200)
401 #endif
402
403 return !FLAGS_SET(ull, GENHD_FL_NO_PART_SCAN);
404 }
405
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;
410
411 assert(sysfs_path);
412
413 if (depth_left == 0)
414 return -EINVAL;
415
416 p = path_join(sysfs_path, "dm/uuid");
417 if (!p)
418 return -ENOMEM;
419
420 r = read_one_line_file(p, &uuids);
421 if (r != -ENOENT) {
422 if (r < 0)
423 return r;
424
425 /* The DM device's uuid attribute is prefixed with "CRYPT-" if this is a dm-crypt device. */
426 if (startswith(uuids, "CRYPT-"))
427 return true;
428 }
429
430 /* Not a dm-crypt device itself. But maybe it is on top of one? Follow the links in the "slaves/"
431 * subdir. */
432
433 p = mfree(p);
434 p = path_join(sysfs_path, "slaves");
435 if (!p)
436 return -ENOMEM;
437
438 d = opendir(p);
439 if (!d) {
440 if (errno == ENOENT) /* Doesn't have underlying devices */
441 return false;
442
443 return -errno;
444 }
445
446 for (;;) {
447 _cleanup_free_ char *q = NULL;
448 struct dirent *de;
449
450 errno = 0;
451 de = readdir_no_dot(d);
452 if (!de) {
453 if (errno != 0)
454 return -errno;
455
456 break; /* No more underlying devices */
457 }
458
459 q = path_join(p, de->d_name);
460 if (!q)
461 return -ENOMEM;
462
463 r = blockdev_is_encrypted(q, depth_left - 1);
464 if (r < 0)
465 return r;
466 if (r == 0) /* we found one that is not encrypted? then propagate that immediately */
467 return false;
468
469 found_encrypted = true;
470 }
471
472 return found_encrypted;
473 }
474
475 int fd_is_encrypted(int fd) {
476 char p[SYS_BLOCK_PATH_MAX(NULL)];
477 dev_t devt;
478 int r;
479
480 r = get_block_device_fd(fd, &devt);
481 if (r < 0)
482 return r;
483 if (r == 0) /* doesn't have a block device */
484 return false;
485
486 xsprintf_sys_block_path(p, NULL, devt);
487
488 return blockdev_is_encrypted(p, 10 /* safety net: maximum recursion depth */);
489 }
490
491 int path_is_encrypted(const char *path) {
492 char p[SYS_BLOCK_PATH_MAX(NULL)];
493 dev_t devt;
494 int r;
495
496 r = get_block_device(path, &devt);
497 if (r < 0)
498 return r;
499 if (r == 0) /* doesn't have a block device */
500 return false;
501
502 xsprintf_sys_block_path(p, NULL, devt);
503
504 return blockdev_is_encrypted(p, 10 /* safety net: maximum recursion depth */);
505 }
506
507 int fd_get_whole_disk(int fd, bool backing, dev_t *ret) {
508 dev_t devt;
509 int r;
510
511 assert(fd >= 0);
512 assert(ret);
513
514 r = fd_get_devnum(fd, backing ? BLOCK_DEVICE_LOOKUP_BACKING : 0, &devt);
515 if (r < 0)
516 return r;
517
518 return block_get_whole_disk(devt, ret);
519 }
520
521 int path_get_whole_disk(const char *path, bool backing, dev_t *ret) {
522 _cleanup_close_ int fd = -EBADF;
523
524 fd = open(path, O_CLOEXEC|O_PATH);
525 if (fd < 0)
526 return -errno;
527
528 return fd_get_whole_disk(fd, backing, ret);
529 }
530
531 int block_device_add_partition(
532 int fd,
533 const char *name,
534 int nr,
535 uint64_t start,
536 uint64_t size) {
537
538 assert(fd >= 0);
539 assert(name);
540 assert(nr > 0);
541
542 struct blkpg_partition bp = {
543 .pno = nr,
544 .start = start,
545 .length = size,
546 };
547
548 struct blkpg_ioctl_arg ba = {
549 .op = BLKPG_ADD_PARTITION,
550 .data = &bp,
551 .datalen = sizeof(bp),
552 };
553
554 if (strlen(name) >= sizeof(bp.devname))
555 return -EINVAL;
556
557 strcpy(bp.devname, name);
558
559 return RET_NERRNO(ioctl(fd, BLKPG, &ba));
560 }
561
562 int block_device_remove_partition(
563 int fd,
564 const char *name,
565 int nr) {
566
567 assert(fd >= 0);
568 assert(name);
569 assert(nr > 0);
570
571 struct blkpg_partition bp = {
572 .pno = nr,
573 };
574
575 struct blkpg_ioctl_arg ba = {
576 .op = BLKPG_DEL_PARTITION,
577 .data = &bp,
578 .datalen = sizeof(bp),
579 };
580
581 if (strlen(name) >= sizeof(bp.devname))
582 return -EINVAL;
583
584 strcpy(bp.devname, name);
585
586 return RET_NERRNO(ioctl(fd, BLKPG, &ba));
587 }
588
589 int block_device_resize_partition(
590 int fd,
591 int nr,
592 uint64_t start,
593 uint64_t size) {
594
595 assert(fd >= 0);
596 assert(nr > 0);
597
598 struct blkpg_partition bp = {
599 .pno = nr,
600 .start = start,
601 .length = size,
602 };
603
604 struct blkpg_ioctl_arg ba = {
605 .op = BLKPG_RESIZE_PARTITION,
606 .data = &bp,
607 .datalen = sizeof(bp),
608 };
609
610 return RET_NERRNO(ioctl(fd, BLKPG, &ba));
611 }
612
613 int partition_enumerator_new(sd_device *dev, sd_device_enumerator **ret) {
614 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
615 const char *s;
616 int r;
617
618 assert(dev);
619 assert(ret);
620
621 /* Refuse invocation on partition block device, insist on "whole" device */
622 r = block_device_is_whole_disk(dev);
623 if (r < 0)
624 return r;
625 if (r == 0)
626 return -ENXIO; /* return a recognizable error */
627
628 r = sd_device_enumerator_new(&e);
629 if (r < 0)
630 return r;
631
632 r = sd_device_enumerator_allow_uninitialized(e);
633 if (r < 0)
634 return r;
635
636 r = sd_device_enumerator_add_match_parent(e, dev);
637 if (r < 0)
638 return r;
639
640 r = sd_device_get_sysname(dev, &s);
641 if (r < 0)
642 return r;
643
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);
647 if (r < 0)
648 return r;
649
650 r = sd_device_enumerator_add_match_subsystem(e, "block", /* match = */ true);
651 if (r < 0)
652 return r;
653
654 r = sd_device_enumerator_add_match_property(e, "DEVTYPE", "partition");
655 if (r < 0)
656 return r;
657
658 *ret = TAKE_PTR(e);
659 return 0;
660 }
661
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;
667 int r, k = 0;
668
669 assert(dev || fd >= 0);
670
671 if (!dev) {
672 r = block_device_new_from_fd(fd, 0, &dev_unref);
673 if (r < 0)
674 return r;
675
676 dev = dev_unref;
677 }
678
679 r = partition_enumerator_new(dev, &e);
680 if (r < 0)
681 return r;
682
683 if (fd < 0) {
684 fd_close = sd_device_open(dev, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|O_RDONLY);
685 if (fd_close < 0)
686 return fd_close;
687
688 fd = fd_close;
689 }
690
691 FOREACH_DEVICE(e, part) {
692 const char *v, *devname;
693 int nr;
694
695 has_partitions = true;
696
697 r = sd_device_get_devname(part, &devname);
698 if (r < 0)
699 return r;
700
701 r = sd_device_get_property_value(part, "PARTN", &v);
702 if (r < 0)
703 return r;
704
705 r = safe_atoi(v, &nr);
706 if (r < 0)
707 return r;
708
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);
712
713 r = block_device_remove_partition(fd, devname, nr);
714 if (r == -ENODEV) {
715 log_debug("Kernel removed partition %s before us, ignoring", devname);
716 continue;
717 }
718 if (r < 0) {
719 log_debug_errno(r, "Failed to remove partition %s: %m", devname);
720 k = k < 0 ? k : r;
721 continue;
722 }
723
724 log_debug("Removed partition %s", devname);
725 }
726
727 return k < 0 ? k : has_partitions;
728 }
729
730 int block_device_has_partitions(sd_device *dev) {
731 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
732 int r;
733
734 assert(dev);
735
736 /* Checks if the specified device currently has partitions. */
737
738 r = partition_enumerator_new(dev, &e);
739 if (r < 0)
740 return r;
741
742 return !!sd_device_enumerator_get_device_first(e);
743 }
744
745 int blockdev_reread_partition_table(sd_device *dev) {
746 _cleanup_close_ int fd = -EBADF;
747
748 assert(dev);
749
750 /* Try to re-read the partition table. This only succeeds if none of the devices is busy. */
751
752 fd = sd_device_open(dev, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
753 if (fd < 0)
754 return fd;
755
756 if (flock(fd, LOCK_EX|LOCK_NB) < 0)
757 return -errno;
758
759 if (ioctl(fd, BLKRRPART, 0) < 0)
760 return -errno;
761
762 return 0;
763 }
764
765 int blockdev_get_sector_size(int fd, uint32_t *ret) {
766 int ssz = 0;
767
768 assert(fd >= 0);
769 assert(ret);
770
771 if (ioctl(fd, BLKSSZGET, &ssz) < 0)
772 return -errno;
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);
775
776 *ret = ssz;
777 return 0;
778 }
779
780 int blockdev_get_root(int level, dev_t *ret) {
781 _cleanup_free_ char *p = NULL;
782 dev_t devno;
783 int r;
784
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.
788 *
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);
794 if (r == -EUCLEAN)
795 return btrfs_log_dev_root(level, r, "root file system");
796 if (r < 0)
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);
800 if (r == -EUCLEAN)
801 return btrfs_log_dev_root(level, r, "/usr");
802 if (r < 0)
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.");
806
807 if (ret)
808 *ret = 0;
809
810 return 0;
811 }
812 }
813 } else if (r < 0)
814 return log_full_errno(level, r, "Failed to read symlink /run/systemd/volatile-root: %m");
815 else {
816 mode_t m;
817 r = device_path_parse_major_minor(p, &m, &devno);
818 if (r < 0)
819 return log_full_errno(level, r, "Failed to parse major/minor device node: %m");
820 if (!S_ISBLK(m))
821 return log_full_errno(level, SYNTHETIC_ERRNO(ENOTBLK), "Volatile root device is of wrong type.");
822 }
823
824 if (ret)
825 *ret = devno;
826
827 return 1;
828 }