summary refs log tree commit diff
diff options
context:
space:
mode:
authorTobias Geerinckx-Rice <me@tobias.gr>2021-09-12 18:07:54 +0200
committerTobias Geerinckx-Rice <me@tobias.gr>2021-09-23 18:17:16 +0200
commit348f0c61efc0f35aedcd0e44bc9fa7bf7f067942 (patch)
treef009f1b4b60f3482f1ad1e81c3028549ebd61433
parent68b219b9f482f09e7c55aaee4b64222d8c86172a (diff)
downloadguix-348f0c61efc0f35aedcd0e44bc9fa7bf7f067942.tar.gz
syscalls: Deduplicate device number conversion.
* guix/cpio.scm (device-number, device->major+minor):
Move to, and subsequently import from, …
* guix/build/syscalls.scm (device-number, device-number->major+minor):
…here.  Note the slight name change.
(mounts): Replace 16-bit open code with a DEVICE-NUMBER call.
* gnu/build/linux-boot.scm (device-number):
Remove duplicate 16-bit implementation in favour of the one above.
(resume-if-hibernated): Reuse DEVICE-NUMBER->MAJOR+MINOR.
-rw-r--r--gnu/build/linux-boot.scm18
-rw-r--r--guix/build/syscalls.scm29
-rw-r--r--guix/cpio.scm21
3 files changed, 36 insertions, 32 deletions
diff --git a/gnu/build/linux-boot.scm b/gnu/build/linux-boot.scm
index 8f0f3eb2fc..8efe6e5f9c 100644
--- a/gnu/build/linux-boot.scm
+++ b/gnu/build/linux-boot.scm
@@ -25,6 +25,7 @@
   #:autoload   (system repl repl) (start-repl)
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-9)
+  #:use-module (srfi srfi-11)
   #:use-module (srfi srfi-26)
   #:use-module (ice-9 match)
   #:use-module (ice-9 rdelim)
@@ -44,7 +45,6 @@
             make-static-device-nodes
             configure-qemu-networking
 
-            device-number
             boot-system))
 
 ;;; Commentary:
@@ -134,14 +134,9 @@ succeeds.  Return nothing otherwise.  The kernel logs any details to dmesg."
            ;; is found on the command line; our canonicalize-device-spec gives
            ;; up after 20 seconds.  We could emulate the former by looping…
            (device (canonicalize-device-spec spec))
-           (rdev (stat:rdev (stat device)))
-           ;; For backwards compatibility, device numbering is a baroque affair.
-           ;; This is the full 64-bit scheme used by glibc's <sys/sysmacros.h>.
-           (major (logior (ash (logand #x00000000000fff00 rdev) -8)
-                          (ash (logand #xfffff00000000000 rdev) -32)))
-           (minor (logior      (logand #x00000000000000ff rdev)
-                          (ash (logand #x00000ffffff00000 rdev) -12))))
-      (format #f "~a:~a" major minor)))
+           (rdev (stat:rdev (stat device))))
+      (let-values (((major minor) (device-number->major+minor rdev)))
+        (format #f "~a:~a" major minor))))
 
   ;; Write the resume DEVICE to this magic file, using the MAJOR:MINOR device
   ;; numbers if possible.  The kernel will immediately try to resume from it.
@@ -392,11 +387,6 @@ networking values.)  Return #t if INTERFACE is up, #f otherwise."
 
     (logand (network-interface-flags sock interface) IFF_UP)))
 
-(define (device-number major minor)
-  "Return the device number for the device with MAJOR and MINOR, for use as
-the last argument of `mknod'."
-  (+ (* major 256) minor))
-
 (define (pidof program)
   "Return the PID of the first presumed instance of PROGRAM."
   (let ((program (basename program)))
diff --git a/guix/build/syscalls.scm b/guix/build/syscalls.scm
index ac1b0c2eea..99a3b45004 100644
--- a/guix/build/syscalls.scm
+++ b/guix/build/syscalls.scm
@@ -7,6 +7,7 @@
 ;;; Copyright © 2020 Julien Lepiller <julien@lepiller.eu>
 ;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
 ;;; Copyright © 2021 Chris Marusich <cmmarusich@gmail.com>
+;;; Copyright © 2021 Tobias Geerinckx-Rice <me@tobias.gr>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -56,6 +57,9 @@
 
             restart-on-EINTR
 
+            device-number
+            device-number->major+minor
+
             mount?
             mount-device-number
             mount-source
@@ -450,6 +454,29 @@ the returned procedure is called."
 
 
 ;;;
+;;; Block devices.
+;;;
+
+;; Convert between major:minor pairs and packed ‘device number’ representation.
+;; XXX These aren't syscalls, but if you squint very hard they are part of the
+;; FFI or however you want to justify me not finding a better fit… :-)
+(define (device-number major minor)     ; see glibc's <sys/sysmacros.h>
+  "Return the device number for the device with MAJOR and MINOR, for use as
+the last argument of `mknod'."
+  (logior (ash (logand #x00000fff major) 8)
+          (ash (logand #xfffff000 major) 32)
+               (logand #x000000ff minor)
+          (ash (logand #xffffff00 minor) 12)))
+
+(define (device-number->major+minor device)     ; see glibc's <sys/sysmacros.h>
+  "Return two values: the major and minor device numbers that make up DEVICE."
+  (values (logior (ash (logand #x00000000000fff00 device) -8)
+                  (ash (logand #xfffff00000000000 device) -32))
+          (logior      (logand #x00000000000000ff device)
+                  (ash (logand #x00000ffffff00000 device) -12))))
+
+
+;;;
 ;;; File systems.
 ;;;
 
@@ -628,7 +655,7 @@ current process."
   (define (string->device-number str)
     (match (string-split str #\:)
       (((= string->number major) (= string->number minor))
-       (+ (* major 256) minor))))
+       (device-number major minor))))
 
   (call-with-input-file "/proc/self/mountinfo"
     (lambda (port)
diff --git a/guix/cpio.scm b/guix/cpio.scm
index 8038a11f3c..d4a7d5f1e0 100644
--- a/guix/cpio.scm
+++ b/guix/cpio.scm
@@ -18,6 +18,8 @@
 ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
 
 (define-module (guix cpio)
+  #:use-module ((guix build syscalls) #:select (device-number
+                                                device-number->major+minor))
   #:use-module ((guix build utils) #:select (dump-port))
   #:use-module (srfi srfi-9)
   #:use-module (srfi srfi-11)
@@ -129,8 +131,8 @@
                            (nlink 1) (mtime 0) (size 0)
                            (dev 0) (rdev 0) (name-size 0))
   "Return a new cpio file header."
-  (let-values (((major minor)   (device->major+minor dev))
-               ((rmajor rminor) (device->major+minor rdev)))
+  (let-values (((major minor)   (device-number->major+minor dev))
+               ((rmajor rminor) (device-number->major+minor rdev)))
     (%make-cpio-header MAGIC
                        inode mode uid gid
                        nlink mtime
@@ -154,21 +156,6 @@ denotes, similar to 'stat:type'."
           (else
            (error "unsupported file type" mode)))))
 
-(define (device-number major minor)     ; see glibc's <sys/sysmacros.h>
-  "Return the device number for the device with MAJOR and MINOR, for use as
-the last argument of `mknod'."
-  (logior (ash (logand #x00000fff major) 8)
-          (ash (logand #xfffff000 major) 32)
-               (logand #x000000ff minor)
-          (ash (logand #xffffff00 minor) 12)))
-
-(define (device->major+minor device)     ; see glibc's <sys/sysmacros.h>
-  "Return two values: the major and minor device numbers that make up DEVICE."
-  (values (logior (ash (logand #x00000000000fff00 device) -8)
-                  (ash (logand #xfffff00000000000 device) -32))
-          (logior      (logand #x00000000000000ff device)
-                  (ash (logand #x00000ffffff00000 device) -12))))
-
 (define* (file->cpio-header file #:optional (file-name file)
                             #:key (stat lstat))
   "Return a cpio header corresponding to the info returned by STAT for FILE,