diff options
| author | Rutherther <rutherther@ditigal.xyz> | 2026-02-04 19:19:19 +0100 |
|---|---|---|
| committer | Maxim Cournoyer <maxim@guixotic.coop> | 2026-02-23 11:46:09 +0900 |
| commit | e3d8fc1147d03b6e6a47f8f1976068ad0faec9ab (patch) | |
| tree | 8bcde4a5676f5a83d3dee9dc2d3da68ef0c5e0f1 /gnu/build | |
| parent | d45da4a5e932aba8d59e08e29ff3db2a3c2179c3 (diff) | |
file-systems: mount-file-system: Guard against missing devices.
When a device with a UUID is missing, canonicalize-device-spec will throw an
error. This error is not handled for mount-may-fail? devices. That means
that if you use UUID device and it isn't available, the boot will hang on
the user-file-systems not being started. All user services depend on that
service.
Also added a test for this behavior.
* gnu/build/file-systems.scm
(mount-file-system): Guard canonicalize-device-spec call.
(canonicalize-device-spec): Throw &partition-lookup-error on missing
partition.
(&partition-lookup-error): New variable.
* gnu/tests/base.scm (%test-missing-file-system): New variable.
Change-Id: I3b8d652251cef421cff6d2fdafb8d9d7d1fc74b5
Reported-By: renbus, on IRC
Signed-off-by: Maxim Cournoyer <maxim@guixotic.coop>
Diffstat (limited to 'gnu/build')
| -rw-r--r-- | gnu/build/file-systems.scm | 80 |
1 files changed, 54 insertions, 26 deletions
diff --git a/gnu/build/file-systems.scm b/gnu/build/file-systems.scm index d25b798b117..72d7f5f2601 100644 --- a/gnu/build/file-systems.scm +++ b/gnu/build/file-systems.scm | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #:use-module (guix i18n) | 37 | #:use-module (guix i18n) |
| 38 | #:use-module (rnrs io ports) | 38 | #:use-module (rnrs io ports) |
| 39 | #:use-module (rnrs bytevectors) | 39 | #:use-module (rnrs bytevectors) |
| 40 | #:use-module (ice-9 exceptions) | ||
| 40 | #:use-module (ice-9 match) | 41 | #:use-module (ice-9 match) |
| 41 | #:use-module (ice-9 rdelim) | 42 | #:use-module (ice-9 rdelim) |
| 42 | #:use-module (ice-9 regex) | 43 | #:use-module (ice-9 regex) |
| @@ -45,6 +46,8 @@ | |||
| 45 | #:autoload (system repl repl) (start-repl) | 46 | #:autoload (system repl repl) (start-repl) |
| 46 | #:use-module (srfi srfi-1) | 47 | #:use-module (srfi srfi-1) |
| 47 | #:use-module (srfi srfi-26) | 48 | #:use-module (srfi srfi-26) |
| 49 | #:use-module (srfi srfi-34) | ||
| 50 | #:use-module (srfi srfi-35) | ||
| 48 | #:export (disk-partitions | 51 | #:export (disk-partitions |
| 49 | partition-label-predicate | 52 | partition-label-predicate |
| 50 | partition-uuid-predicate | 53 | partition-uuid-predicate |
| @@ -65,6 +68,9 @@ | |||
| 65 | 68 | ||
| 66 | cleanly-unmounted-ext2? | 69 | cleanly-unmounted-ext2? |
| 67 | 70 | ||
| 71 | partition-lookup-error? | ||
| 72 | &partition-lookup-error | ||
| 73 | |||
| 68 | bind-mount | 74 | bind-mount |
| 69 | 75 | ||
| 70 | system*/tty | 76 | system*/tty |
| @@ -1182,6 +1188,10 @@ were found." | |||
| 1182 | (define find-partition-by-luks-uuid | 1188 | (define find-partition-by-luks-uuid |
| 1183 | (find-partition luks-partition-uuid-predicate)) | 1189 | (find-partition luks-partition-uuid-predicate)) |
| 1184 | 1190 | ||
| 1191 | (define-condition-type &partition-lookup-error &condition | ||
| 1192 | partition-lookup-error? | ||
| 1193 | (spec partition-lookup-error-spec)) | ||
| 1194 | |||
| 1185 | 1195 | ||
| 1186 | (define (canonicalize-device-spec spec) | 1196 | (define (canonicalize-device-spec spec) |
| 1187 | "Return the device name corresponding to SPEC, which can be a <uuid>, a | 1197 | "Return the device name corresponding to SPEC, which can be a <uuid>, a |
| @@ -1201,7 +1211,9 @@ file name or an nfs-root containing ':/')." | |||
| 1201 | ;; Some devices take a bit of time to appear, most notably USB | 1211 | ;; Some devices take a bit of time to appear, most notably USB |
| 1202 | ;; storage devices. Thus, wait for the device to appear. | 1212 | ;; storage devices. Thus, wait for the device to appear. |
| 1203 | (if (> count max-trials) | 1213 | (if (> count max-trials) |
| 1204 | (error "failed to resolve partition" (fmt spec)) | 1214 | (raise (condition |
| 1215 | (&partition-lookup-error | ||
| 1216 | (spec (fmt spec))))) | ||
| 1205 | (begin | 1217 | (begin |
| 1206 | (format #t "waiting for partition '~a' to appear...~%" | 1218 | (format #t "waiting for partition '~a' to appear...~%" |
| 1207 | (fmt spec)) | 1219 | (fmt spec)) |
| @@ -1319,6 +1331,14 @@ corresponds to the symbols listed in FLAGS." | |||
| 1319 | (() | 1331 | (() |
| 1320 | 0)))) | 1332 | 0)))) |
| 1321 | 1333 | ||
| 1334 | (define kind-and-args-exception? | ||
| 1335 | (exception-predicate &exception-with-kind-and-args)) | ||
| 1336 | |||
| 1337 | (define (system-error? exception) | ||
| 1338 | "Return true if EXCEPTION is a Guile 'system-error exception." | ||
| 1339 | (and (kind-and-args-exception? exception) | ||
| 1340 | (eq? 'system-error (exception-kind exception)))) | ||
| 1341 | |||
| 1322 | (define* (mount-file-system fs #:key (root "/root") | 1342 | (define* (mount-file-system fs #:key (root "/root") |
| 1323 | (check? (file-system-check? fs)) | 1343 | (check? (file-system-check? fs)) |
| 1324 | (skip-check-if-clean? | 1344 | (skip-check-if-clean? |
| @@ -1339,8 +1359,8 @@ corresponds to the symbols listed in FLAGS." | |||
| 1339 | (host-part (string-take source idx)) | 1359 | (host-part (string-take source idx)) |
| 1340 | ;; Strip [] from around host if present | 1360 | ;; Strip [] from around host if present |
| 1341 | (host (match (string-split host-part (string->char-set "[]")) | 1361 | (host (match (string-split host-part (string->char-set "[]")) |
| 1342 | (("" h "") h) | 1362 | (("" h "") h) |
| 1343 | ((h) h))) | 1363 | ((h) h))) |
| 1344 | (inet-addr (host-to-ip host "nfs"))) | 1364 | (inet-addr (host-to-ip host "nfs"))) |
| 1345 | ;; Mounting an NFS file system requires passing the address | 1365 | ;; Mounting an NFS file system requires passing the address |
| 1346 | ;; of the server in the addr= option | 1366 | ;; of the server in the addr= option |
| @@ -1426,26 +1446,37 @@ corresponds to the symbols listed in FLAGS." | |||
| 1426 | "," 'prefix) | 1446 | "," 'prefix) |
| 1427 | ""))))) | 1447 | ""))))) |
| 1428 | 1448 | ||
| 1429 | (let* ((type (file-system-type fs)) | 1449 | (guard (c ((partition-lookup-error? c) |
| 1430 | (source (canonicalize-device-spec (file-system-device fs))) | 1450 | (format (current-error-port) |
| 1431 | (target (string-append root "/" | 1451 | "could not find the partition: ~a~%" |
| 1432 | (file-system-mount-point fs))) | 1452 | (partition-lookup-error-spec c)) |
| 1433 | (flags (logior (mount-flags->bit-mask (file-system-flags fs)) | 1453 | (unless (file-system-mount-may-fail? fs) |
| 1434 | 1454 | (raise c))) | |
| 1435 | ;; For bind mounts, preserve the original flags such | 1455 | ((system-error? c) |
| 1436 | ;; as MS_NOSUID, etc. Failing to do that, the | 1456 | (format (current-error-port) |
| 1437 | ;; MS_REMOUNT call below fails with EPERM. | 1457 | "could not mount partition ~a: ~a~%" |
| 1438 | ;; See <https://bugs.gnu.org/46292> | 1458 | (file-system-device fs) |
| 1439 | (if (memq 'bind-mount (file-system-flags fs)) | 1459 | (exception-message c)) |
| 1440 | (statfs-flags->mount-flags | 1460 | (unless (file-system-mount-may-fail? fs) |
| 1441 | (file-system-mount-flags (statfs source))) | 1461 | (raise c)))) |
| 1442 | 0))) | 1462 | (let* ((type (file-system-type fs)) |
| 1443 | (options (file-system-options fs))) | 1463 | (source (canonicalize-device-spec (file-system-device fs))) |
| 1444 | (when check? | 1464 | (target (string-append root "/" |
| 1445 | (check-file-system source type (not skip-check-if-clean?) repair)) | 1465 | (file-system-mount-point fs))) |
| 1466 | (flags (logior (mount-flags->bit-mask (file-system-flags fs)) | ||
| 1467 | |||
| 1468 | ;; For bind mounts, preserve the original flags such | ||
| 1469 | ;; as MS_NOSUID, etc. Failing to do that, the | ||
| 1470 | ;; MS_REMOUNT call below fails with EPERM. | ||
| 1471 | ;; See <https://bugs.gnu.org/46292> | ||
| 1472 | (if (memq 'bind-mount (file-system-flags fs)) | ||
| 1473 | (statfs-flags->mount-flags | ||
| 1474 | (file-system-mount-flags (statfs source))) | ||
| 1475 | 0))) | ||
| 1476 | (options (file-system-options fs))) | ||
| 1477 | (when check? | ||
| 1478 | (check-file-system source type (not skip-check-if-clean?) repair)) | ||
| 1446 | 1479 | ||
| 1447 | (catch 'system-error | ||
| 1448 | (lambda () | ||
| 1449 | ;; Create the mount point. Most of the time this is a directory, but | 1480 | ;; Create the mount point. Most of the time this is a directory, but |
| 1450 | ;; in the case of a bind mount, a regular file or socket may be | 1481 | ;; in the case of a bind mount, a regular file or socket may be |
| 1451 | ;; needed. | 1482 | ;; needed. |
| @@ -1474,10 +1505,7 @@ corresponds to the symbols listed in FLAGS." | |||
| 1474 | (when (and (= MS_BIND (logand flags MS_BIND)) | 1505 | (when (and (= MS_BIND (logand flags MS_BIND)) |
| 1475 | (= MS_RDONLY (logand flags MS_RDONLY))) | 1506 | (= MS_RDONLY (logand flags MS_RDONLY))) |
| 1476 | (let ((flags (logior MS_REMOUNT flags))) | 1507 | (let ((flags (logior MS_REMOUNT flags))) |
| 1477 | (mount source target type flags options)))) | 1508 | (mount source target type flags options)))))) |
| 1478 | (lambda args | ||
| 1479 | (or (file-system-mount-may-fail? fs) | ||
| 1480 | (apply throw args)))))) | ||
| 1481 | 1509 | ||
| 1482 | (define %device-name-regexp "/dev/[hsvw]d([abcd])([0-9]*)") | 1510 | (define %device-name-regexp "/dev/[hsvw]d([abcd])([0-9]*)") |
| 1483 | (define %hurd-device-name-regexp "part:([0-9]*):device:[hw]d([0-9]*)") | 1511 | (define %hurd-device-name-regexp "part:([0-9]*):device:[hw]d([0-9]*)") |
