summary refs log tree commit diff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2014-06-02 23:48:55 +0200
committerLudovic Courtès <ludo@gnu.org>2014-06-02 23:48:55 +0200
commit2405858a0477aca880bb32c032df459de68e1bfd (patch)
tree29e8d3bac43f88ef4dabaef6a5b20fb08f304b90
parent0497ba3b260527d4184a0fcb22d6ab30e5e11a63 (diff)
downloadguix-2405858a0477aca880bb32c032df459de68e1bfd.tar.gz
linux-initrd: Wait for devices to appear when resolving a label.
* guix/build/linux-initrd.scm (canonicalize-device-spec): Add #:title
  parameter.  When resolving a label, wait a little and try several
  times before bailing out.
-rw-r--r--guix/build/linux-initrd.scm50
1 files changed, 44 insertions, 6 deletions
diff --git a/guix/build/linux-initrd.scm b/guix/build/linux-initrd.scm
index d7de9c14ee..05f6bf14bf 100644
--- a/guix/build/linux-initrd.scm
+++ b/guix/build/linux-initrd.scm
@@ -204,12 +204,50 @@ were found."
                (disk-partitions))
          (cut string-append "/dev/" <>)))
 
-(define (canonicalize-device-spec spec)
-  "Given SPEC, a string such as \"/dev/sda1\" or \"my-root-part\", return the
-corresponding device name."
-  (if (string-prefix? "/" spec)
-      spec
-      (or (find-partition-by-label spec) spec)))
+(define* (canonicalize-device-spec spec #:optional (title 'any))
+  "Return the device name corresponding to SPEC.  TITLE is a symbol, one of
+the following:
+
+  • 'device', in which case SPEC is known to designate a device node--e.g.,
+     \"/dev/sda1\";
+  • 'label', in which case SPEC is known to designate a partition label--e.g.,
+     \"my-root-part\";
+  • 'any', in which case SPEC can be anything.
+"
+  (define max-trials
+    ;; Number of times we retry partition label resolution.
+    7)
+
+  (define canonical-title
+    ;; The realm of canonicalization.
+    (if (eq? title 'any)
+        (if (string-prefix? "/" spec)
+            'device
+            'label)
+        title))
+
+  (case canonical-title
+    ((device)
+     ;; Nothing to do.
+     spec)
+    ((label)
+     ;; Resolve the label.
+     (let loop ((count 0))
+       (let ((device (find-partition-by-label spec)))
+         (or device
+             ;; Some devices take a bit of time to appear, most notably USB
+             ;; storage devices.  Thus, wait for the device to appear.
+             (if (> count max-trials)
+                 (begin
+                   (format (current-error-port)
+                           "failed to resolve partition label: ~s~%" spec)
+                   (start-repl))
+                 (begin
+                   (sleep 1)
+                   (loop (+ 1 count))))))))
+    ;; TODO: Add support for UUIDs.
+    (else
+     (error "unknown device title" title))))
 
 (define* (make-disk-device-nodes base major #:optional (minor 0))
   "Make the block device nodes around BASE (something like \"/root/dev/sda\")