file-systems.scm 14 KB

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