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.
This commit is contained in:
Tobias Geerinckx-Rice 2021-09-12 18:07:54 +02:00
parent 68b219b9f4
commit 348f0c61ef
No known key found for this signature in database
GPG Key ID: 0DB0FF884F556D79
3 changed files with 36 additions and 32 deletions

View File

@ -25,6 +25,7 @@
#:autoload (system repl repl) (start-repl) #:autoload (system repl repl) (start-repl)
#:use-module (srfi srfi-1) #:use-module (srfi srfi-1)
#:use-module (srfi srfi-9) #:use-module (srfi srfi-9)
#:use-module (srfi srfi-11)
#:use-module (srfi srfi-26) #:use-module (srfi srfi-26)
#:use-module (ice-9 match) #:use-module (ice-9 match)
#:use-module (ice-9 rdelim) #:use-module (ice-9 rdelim)
@ -44,7 +45,6 @@
make-static-device-nodes make-static-device-nodes
configure-qemu-networking configure-qemu-networking
device-number
boot-system)) boot-system))
;;; Commentary: ;;; 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 ;; is found on the command line; our canonicalize-device-spec gives
;; up after 20 seconds. We could emulate the former by looping… ;; up after 20 seconds. We could emulate the former by looping…
(device (canonicalize-device-spec spec)) (device (canonicalize-device-spec spec))
(rdev (stat:rdev (stat device))) (rdev (stat:rdev (stat device))))
;; For backwards compatibility, device numbering is a baroque affair. (let-values (((major minor) (device-number->major+minor rdev)))
;; This is the full 64-bit scheme used by glibc's <sys/sysmacros.h>. (format #f "~a:~a" major minor))))
(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)))
;; Write the resume DEVICE to this magic file, using the MAJOR:MINOR device ;; 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. ;; 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))) (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) (define (pidof program)
"Return the PID of the first presumed instance of PROGRAM." "Return the PID of the first presumed instance of PROGRAM."
(let ((program (basename program))) (let ((program (basename program)))

View File

@ -7,6 +7,7 @@
;;; Copyright © 2020 Julien Lepiller <julien@lepiller.eu> ;;; Copyright © 2020 Julien Lepiller <julien@lepiller.eu>
;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org> ;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2021 Chris Marusich <cmmarusich@gmail.com> ;;; Copyright © 2021 Chris Marusich <cmmarusich@gmail.com>
;;; Copyright © 2021 Tobias Geerinckx-Rice <me@tobias.gr>
;;; ;;;
;;; This file is part of GNU Guix. ;;; This file is part of GNU Guix.
;;; ;;;
@ -56,6 +57,9 @@
restart-on-EINTR restart-on-EINTR
device-number
device-number->major+minor
mount? mount?
mount-device-number mount-device-number
mount-source mount-source
@ -448,6 +452,29 @@ the returned procedure is called."
(module-define! (current-module) 'variable value) (module-define! (current-module) 'variable value)
(module-export! (current-module) '(variable))))))) (module-export! (current-module) '(variable)))))))
;;;
;;; 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. ;;; File systems.
@ -628,7 +655,7 @@ current process."
(define (string->device-number str) (define (string->device-number str)
(match (string-split str #\:) (match (string-split str #\:)
(((= string->number major) (= string->number minor)) (((= string->number major) (= string->number minor))
(+ (* major 256) minor)))) (device-number major minor))))
(call-with-input-file "/proc/self/mountinfo" (call-with-input-file "/proc/self/mountinfo"
(lambda (port) (lambda (port)

View File

@ -18,6 +18,8 @@
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (guix cpio) (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 ((guix build utils) #:select (dump-port))
#:use-module (srfi srfi-9) #:use-module (srfi srfi-9)
#:use-module (srfi srfi-11) #:use-module (srfi srfi-11)
@ -129,8 +131,8 @@
(nlink 1) (mtime 0) (size 0) (nlink 1) (mtime 0) (size 0)
(dev 0) (rdev 0) (name-size 0)) (dev 0) (rdev 0) (name-size 0))
"Return a new cpio file header." "Return a new cpio file header."
(let-values (((major minor) (device->major+minor dev)) (let-values (((major minor) (device-number->major+minor dev))
((rmajor rminor) (device->major+minor rdev))) ((rmajor rminor) (device-number->major+minor rdev)))
(%make-cpio-header MAGIC (%make-cpio-header MAGIC
inode mode uid gid inode mode uid gid
nlink mtime nlink mtime
@ -154,21 +156,6 @@ denotes, similar to 'stat:type'."
(else (else
(error "unsupported file type" mode))))) (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) (define* (file->cpio-header file #:optional (file-name file)
#:key (stat lstat)) #:key (stat lstat))
"Return a cpio header corresponding to the info returned by STAT for FILE, "Return a cpio header corresponding to the info returned by STAT for FILE,