file-systems.scm 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
  3. ;;;
  4. ;;; This file is part of GNU Guix.
  5. ;;;
  6. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  7. ;;; under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation; either version 3 of the License, or (at
  9. ;;; your option) any later version.
  10. ;;;
  11. ;;; GNU Guix is distributed in the hope that it will be useful, but
  12. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;;; GNU General Public License for more details.
  15. ;;;
  16. ;;; You should have received a copy of the GNU General Public License
  17. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  18. (define-module (gnu system file-systems)
  19. #:use-module (ice-9 match)
  20. #:use-module (srfi srfi-1)
  21. #:use-module (guix records)
  22. #:use-module (gnu system uuid)
  23. #:re-export (uuid ;backward compatibility
  24. string->uuid
  25. uuid->string)
  26. #:export (<file-system>
  27. file-system
  28. file-system?
  29. file-system-device
  30. file-system-title
  31. file-system-mount-point
  32. file-system-type
  33. file-system-needed-for-boot?
  34. file-system-flags
  35. file-system-options
  36. file-system-mount?
  37. file-system-check?
  38. file-system-create-mount-point?
  39. file-system-dependencies
  40. file-system-location
  41. file-system-type-predicate
  42. file-system->spec
  43. spec->file-system
  44. specification->file-system-mapping
  45. %fuse-control-file-system
  46. %binary-format-file-system
  47. %shared-memory-file-system
  48. %pseudo-terminal-file-system
  49. %tty-gid
  50. %immutable-store
  51. %control-groups
  52. %elogind-file-systems
  53. %base-file-systems
  54. %container-file-systems
  55. <file-system-mapping>
  56. file-system-mapping
  57. file-system-mapping?
  58. file-system-mapping-source
  59. file-system-mapping-target
  60. file-system-mapping-writable?
  61. file-system-mapping->bind-mount
  62. %store-mapping
  63. %network-configuration-files
  64. %network-file-mappings))
  65. ;;; Commentary:
  66. ;;;
  67. ;;; Declaring file systems to be mounted.
  68. ;;;
  69. ;;; Note: this file system is used both in the Shepherd and on the "host
  70. ;;; side", so it must not include (gnu packages …) modules.
  71. ;;;
  72. ;;; Code:
  73. ;; File system declaration.
  74. (define-record-type* <file-system> file-system
  75. make-file-system
  76. file-system?
  77. (device file-system-device) ; string
  78. (title file-system-title ; 'device | 'label | 'uuid
  79. (default 'device))
  80. (mount-point file-system-mount-point) ; string
  81. (type file-system-type) ; string
  82. (flags file-system-flags ; list of symbols
  83. (default '()))
  84. (options file-system-options ; string or #f
  85. (default #f))
  86. (mount? file-system-mount? ; Boolean
  87. (default #t))
  88. (needed-for-boot? %file-system-needed-for-boot? ; Boolean
  89. (default #f))
  90. (check? file-system-check? ; Boolean
  91. (default #t))
  92. (create-mount-point? file-system-create-mount-point? ; Boolean
  93. (default #f))
  94. (dependencies file-system-dependencies ; list of <file-system>
  95. (default '())) ; or <mapped-device>
  96. (location file-system-location
  97. (default (current-source-location))
  98. (innate)))
  99. ;; Note: This module is used both on the build side and on the host side.
  100. ;; Arrange not to pull (guix store) and (guix config) because the latter
  101. ;; differs from user to user.
  102. (define (%store-prefix)
  103. "Return the store prefix."
  104. (cond ((resolve-module '(guix store) #:ensure #f)
  105. =>
  106. (lambda (store)
  107. ((module-ref store '%store-prefix))))
  108. ((getenv "NIX_STORE")
  109. => identity)
  110. (else
  111. "/gnu/store")))
  112. (define %not-slash
  113. (char-set-complement (char-set #\/)))
  114. (define (file-prefix? file1 file2)
  115. "Return #t if FILE1 denotes the name of a file that is a parent of FILE2,
  116. where both FILE1 and FILE2 are absolute file name. For example:
  117. (file-prefix? \"/gnu\" \"/gnu/store\")
  118. => #t
  119. (file-prefix? \"/gn\" \"/gnu/store\")
  120. => #f
  121. "
  122. (and (string-prefix? "/" file1)
  123. (string-prefix? "/" file2)
  124. (let loop ((file1 (string-tokenize file1 %not-slash))
  125. (file2 (string-tokenize file2 %not-slash)))
  126. (match file1
  127. (()
  128. #t)
  129. ((head1 tail1 ...)
  130. (match file2
  131. ((head2 tail2 ...)
  132. (and (string=? head1 head2) (loop tail1 tail2)))
  133. (()
  134. #f)))))))
  135. (define (file-system-needed-for-boot? fs)
  136. "Return true if FS has the 'needed-for-boot?' flag set, or if it holds the
  137. store--e.g., if FS is the root file system."
  138. (or (%file-system-needed-for-boot? fs)
  139. (and (file-prefix? (file-system-mount-point fs) (%store-prefix))
  140. (not (memq 'bind-mount (file-system-flags fs))))))
  141. (define (file-system->spec fs)
  142. "Return a list corresponding to file-system FS that can be passed to the
  143. initrd code."
  144. (match fs
  145. (($ <file-system> device title mount-point type flags options _ _ check?)
  146. (list (if (uuid? device)
  147. (uuid-bytevector device)
  148. device)
  149. title mount-point type flags options check?))))
  150. (define (spec->file-system sexp)
  151. "Deserialize SEXP, a list, to the corresponding <file-system> object."
  152. (match sexp
  153. ((device title mount-point type flags options check?)
  154. (file-system
  155. (device device) (title title)
  156. (mount-point mount-point) (type type)
  157. (flags flags) (options options)
  158. (check? check?)))))
  159. (define (specification->file-system-mapping spec writable?)
  160. "Read the SPEC and return the corresponding <file-system-mapping>. SPEC is
  161. a string of the form \"SOURCE\" or \"SOURCE=TARGET\". The former specifies
  162. that SOURCE from the host should be mounted at SOURCE in the other system.
  163. The latter format specifies that SOURCE from the host should be mounted at
  164. TARGET in the other system."
  165. (let ((index (string-index spec #\=)))
  166. (if index
  167. (file-system-mapping
  168. (source (substring spec 0 index))
  169. (target (substring spec (+ 1 index)))
  170. (writable? writable?))
  171. (file-system-mapping
  172. (source spec)
  173. (target spec)
  174. (writable? writable?)))))
  175. ;;;
  176. ;;; Common file systems.
  177. ;;;
  178. (define %fuse-control-file-system
  179. ;; Control file system for Linux' file systems in user-space (FUSE).
  180. (file-system
  181. (device "fusectl")
  182. (mount-point "/sys/fs/fuse/connections")
  183. (type "fusectl")
  184. (check? #f)))
  185. (define %binary-format-file-system
  186. ;; Support for arbitrary executable binary format.
  187. (file-system
  188. (device "binfmt_misc")
  189. (mount-point "/proc/sys/fs/binfmt_misc")
  190. (type "binfmt_misc")
  191. (check? #f)))
  192. (define %tty-gid
  193. ;; ID of the 'tty' group. Allocate it statically to make it easy to refer
  194. ;; to it from here and from the 'tty' group definitions.
  195. 996)
  196. (define %pseudo-terminal-file-system
  197. ;; The pseudo-terminal file system. It needs to be mounted so that
  198. ;; statfs(2) returns DEVPTS_SUPER_MAGIC like libc's getpt(3) expects (and
  199. ;; thus openpty(3) and its users, such as xterm.)
  200. (file-system
  201. (device "none")
  202. (mount-point "/dev/pts")
  203. (type "devpts")
  204. (check? #f)
  205. (needed-for-boot? #f)
  206. (create-mount-point? #t)
  207. (options (string-append "gid=" (number->string %tty-gid) ",mode=620"))))
  208. (define %shared-memory-file-system
  209. ;; Shared memory.
  210. (file-system
  211. (device "tmpfs")
  212. (mount-point "/dev/shm")
  213. (type "tmpfs")
  214. (check? #f)
  215. (flags '(no-suid no-dev))
  216. (options "size=50%") ;TODO: make size configurable
  217. (create-mount-point? #t)))
  218. (define %immutable-store
  219. ;; Read-only store to avoid users or daemons accidentally modifying it.
  220. ;; 'guix-daemon' has provisions to remount it read-write in its own name
  221. ;; space.
  222. (file-system
  223. (device (%store-prefix))
  224. (mount-point (%store-prefix))
  225. (type "none")
  226. (check? #f)
  227. (flags '(read-only bind-mount))))
  228. (define %control-groups
  229. (let ((parent (file-system
  230. (device "cgroup")
  231. (mount-point "/sys/fs/cgroup")
  232. (type "tmpfs")
  233. (check? #f))))
  234. (cons parent
  235. (map (lambda (subsystem)
  236. (file-system
  237. (device "cgroup")
  238. (mount-point (string-append "/sys/fs/cgroup/" subsystem))
  239. (type "cgroup")
  240. (check? #f)
  241. (options subsystem)
  242. (create-mount-point? #t)
  243. ;; This must be mounted after, and unmounted before the
  244. ;; parent directory.
  245. (dependencies (list parent))))
  246. '("cpuset" "cpu" "cpuacct" "memory" "devices" "freezer"
  247. "blkio" "perf_event" "hugetlb")))))
  248. (define %elogind-file-systems
  249. ;; We don't use systemd, but these file systems are needed for elogind,
  250. ;; which was extracted from systemd.
  251. (list (file-system
  252. (device "none")
  253. (mount-point "/run/systemd")
  254. (type "tmpfs")
  255. (check? #f)
  256. (flags '(no-suid no-dev no-exec))
  257. (options "mode=0755")
  258. (create-mount-point? #t))
  259. (file-system
  260. (device "none")
  261. (mount-point "/run/user")
  262. (type "tmpfs")
  263. (check? #f)
  264. (flags '(no-suid no-dev no-exec))
  265. (options "mode=0755")
  266. (create-mount-point? #t))
  267. ;; Elogind uses cgroups to organize processes, allowing it to map PIDs
  268. ;; to sessions. Elogind's cgroup hierarchy isn't associated with any
  269. ;; resource controller ("subsystem").
  270. (file-system
  271. (device "cgroup")
  272. (mount-point "/sys/fs/cgroup/elogind")
  273. (type "cgroup")
  274. (check? #f)
  275. (options "none,name=elogind")
  276. (create-mount-point? #t)
  277. (dependencies (list (car %control-groups))))))
  278. (define %base-file-systems
  279. ;; List of basic file systems to be mounted. Note that /proc and /sys are
  280. ;; currently mounted by the initrd.
  281. (append (list %pseudo-terminal-file-system
  282. %shared-memory-file-system
  283. %immutable-store)
  284. %control-groups))
  285. ;; File systems for Linux containers differ from %base-file-systems in that
  286. ;; they impose additional restrictions such as no-exec or need different
  287. ;; options to function properly.
  288. ;;
  289. ;; The file system flags and options conform to the libcontainer
  290. ;; specification:
  291. ;; https://github.com/docker/libcontainer/blob/master/SPEC.md#filesystem
  292. (define %container-file-systems
  293. (list
  294. ;; Pseudo-terminal file system.
  295. (file-system
  296. (device "none")
  297. (mount-point "/dev/pts")
  298. (type "devpts")
  299. (flags '(no-exec no-suid))
  300. (needed-for-boot? #t)
  301. (create-mount-point? #t)
  302. (check? #f)
  303. (options "newinstance,ptmxmode=0666,mode=620"))
  304. ;; Shared memory file system.
  305. (file-system
  306. (device "tmpfs")
  307. (mount-point "/dev/shm")
  308. (type "tmpfs")
  309. (flags '(no-exec no-suid no-dev))
  310. (options "mode=1777,size=65536k")
  311. (needed-for-boot? #t)
  312. (create-mount-point? #t)
  313. (check? #f))
  314. ;; Message queue file system.
  315. (file-system
  316. (device "mqueue")
  317. (mount-point "/dev/mqueue")
  318. (type "mqueue")
  319. (flags '(no-exec no-suid no-dev))
  320. (needed-for-boot? #t)
  321. (create-mount-point? #t)
  322. (check? #f))))
  323. ;;;
  324. ;;; Shared file systems, for VMs/containers.
  325. ;;;
  326. ;; Mapping of host file system SOURCE to mount point TARGET in the guest.
  327. (define-record-type* <file-system-mapping> file-system-mapping
  328. make-file-system-mapping
  329. file-system-mapping?
  330. (source file-system-mapping-source) ;string
  331. (target file-system-mapping-target) ;string
  332. (writable? file-system-mapping-writable? ;Boolean
  333. (default #f)))
  334. (define (file-system-mapping->bind-mount mapping)
  335. "Return a file system that realizes MAPPING, a <file-system-mapping>, using
  336. a bind mount."
  337. (match mapping
  338. (($ <file-system-mapping> source target writable?)
  339. (file-system
  340. (mount-point target)
  341. (device source)
  342. (type "none")
  343. (flags (if writable?
  344. '(bind-mount)
  345. '(bind-mount read-only)))
  346. (check? #f)
  347. (create-mount-point? #t)))))
  348. (define %store-mapping
  349. ;; Mapping of the host's store into the guest.
  350. (file-system-mapping
  351. (source (%store-prefix))
  352. (target (%store-prefix))
  353. (writable? #f)))
  354. (define %network-configuration-files
  355. ;; List of essential network configuration files.
  356. '("/etc/resolv.conf"
  357. "/etc/nsswitch.conf"
  358. "/etc/services"
  359. "/etc/hosts"))
  360. (define %network-file-mappings
  361. ;; List of file mappings for essential network files.
  362. (filter-map (lambda (file)
  363. (file-system-mapping
  364. (source file)
  365. (target file)
  366. ;; XXX: On some GNU/Linux systems, /etc/resolv.conf is a
  367. ;; symlink to a file in a tmpfs which, for an unknown reason,
  368. ;; cannot be bind mounted read-only within the container.
  369. (writable? (string=? file "/etc/resolv.conf"))))
  370. %network-configuration-files))
  371. (define (file-system-type-predicate type)
  372. "Return a predicate that, when passed a file system, returns #t if that file
  373. system has the given TYPE."
  374. (lambda (fs)
  375. (string=? (file-system-type fs) type)))
  376. ;;; file-systems.scm ends here