FreeBSD kernel kern code
vfs_mountroot.c
Go to the documentation of this file.
1 /*-
2  * Copyright (c) 2010 Marcel Moolenaar
3  * Copyright (c) 1999-2004 Poul-Henning Kamp
4  * Copyright (c) 1999 Michael Smith
5  * Copyright (c) 1989, 1993
6  * The Regents of the University of California. All rights reserved.
7  * (c) UNIX System Laboratories, Inc.
8  * All or some portions of this file are derived from material licensed
9  * to the University of California by American Telephone and Telegraph
10  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
11  * the permission of UNIX System Laboratories, Inc.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  * notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution.
21  * 4. Neither the name of the University nor the names of its contributors
22  * may be used to endorse or promote products derived from this software
23  * without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 
38 #include "opt_rootdevname.h"
39 
40 #include <sys/cdefs.h>
41 __FBSDID("$BSDSUniX$");
42 
43 #include <sys/param.h>
44 #include <sys/conf.h>
45 #include <sys/cons.h>
46 #include <sys/fcntl.h>
47 #include <sys/jail.h>
48 #include <sys/kernel.h>
49 #include <sys/malloc.h>
50 #include <sys/mdioctl.h>
51 #include <sys/mount.h>
52 #include <sys/mutex.h>
53 #include <sys/namei.h>
54 #include <sys/priv.h>
55 #include <sys/proc.h>
56 #include <sys/filedesc.h>
57 #include <sys/reboot.h>
58 #include <sys/sbuf.h>
59 #include <sys/stat.h>
60 #include <sys/syscallsubr.h>
61 #include <sys/sysproto.h>
62 #include <sys/sx.h>
63 #include <sys/sysctl.h>
64 #include <sys/sysent.h>
65 #include <sys/systm.h>
66 #include <sys/vnode.h>
67 
68 #include <geom/geom.h>
69 
70 /*
71  * The root filesystem is detailed in the kernel environment variable
72  * vfs.root.mountfrom, which is expected to be in the general format
73  *
74  * <vfsname>:[<path>][ <vfsname>:[<path>] ...]
75  * vfsname := the name of a VFS known to the kernel and capable
76  * of being mounted as root
77  * path := disk device name or other data used by the filesystem
78  * to locate its physical store
79  *
80  * If the environment variable vfs.root.mountfrom is a space separated list,
81  * each list element is tried in turn and the root filesystem will be mounted
82  * from the first one that suceeds.
83  *
84  * The environment variable vfs.root.mountfrom.options is a comma delimited
85  * set of string mount options. These mount options must be parseable
86  * by nmount() in the kernel.
87  */
88 
89 static int parse_mount(char **);
90 static struct mntarg *parse_mountroot_options(struct mntarg *, const char *);
91 
92 /*
93  * The vnode of the system's root (/ in the filesystem, without chroot
94  * active.)
95  */
96 struct vnode *rootvnode;
97 
98 char *rootdevnames[2] = {NULL, NULL};
99 
100 struct mtx root_holds_mtx;
101 MTX_SYSINIT(root_holds, &root_holds_mtx, "root_holds", MTX_DEF);
102 
104  const char *who;
105  LIST_ENTRY(root_hold_token) list;
106 };
107 
108 static LIST_HEAD(, root_hold_token) root_holds =
109  LIST_HEAD_INITIALIZER(root_holds);
110 
111 enum action {
112  A_CONTINUE,
113  A_PANIC,
114  A_REBOOT,
115  A_RETRY
116 };
117 
118 static enum action root_mount_onfail = A_CONTINUE;
119 
120 static int root_mount_mddev;
122 
123 /* By default wait up to 3 seconds for devices to appear. */
124 static int root_mount_timeout = 3;
125 TUNABLE_INT("vfs.mountroot.timeout", &root_mount_timeout);
126 
127 struct root_hold_token *
128 root_mount_hold(const char *identifier)
129 {
130  struct root_hold_token *h;
131 
132  if (root_mounted())
133  return (NULL);
134 
135  h = malloc(sizeof *h, M_DEVBUF, M_ZERO | M_WAITOK);
136  h->who = identifier;
137  mtx_lock(&root_holds_mtx);
138  LIST_INSERT_HEAD(&root_holds, h, list);
139  mtx_unlock(&root_holds_mtx);
140  return (h);
141 }
142 
143 void
145 {
146 
147  if (h == NULL)
148  return;
149  mtx_lock(&root_holds_mtx);
150  LIST_REMOVE(h, list);
151  wakeup(&root_holds);
152  mtx_unlock(&root_holds_mtx);
153  free(h, M_DEVBUF);
154 }
155 
156 int
158 {
159 
160  /* No mutex is acquired here because int stores are atomic. */
161  return (root_mount_complete);
162 }
163 
164 void
166 {
167 
168  /*
169  * Panic on an obvious deadlock - the function can't be called from
170  * a thread which is doing the whole SYSINIT stuff.
171  */
172  KASSERT(curthread->td_proc->p_pid != 0,
173  ("root_mount_wait: cannot be called from the swapper thread"));
174  mtx_lock(&root_holds_mtx);
175  while (!root_mount_complete) {
176  msleep(&root_mount_complete, &root_holds_mtx, PZERO, "rootwait",
177  hz);
178  }
179  mtx_unlock(&root_holds_mtx);
180 }
181 
182 static void
184 {
185  struct proc *p;
186 
187  if (VFS_ROOT(TAILQ_FIRST(&mountlist), LK_EXCLUSIVE, &rootvnode))
188  panic("Cannot find root vnode");
189 
190  VOP_UNLOCK(rootvnode, 0);
191 
192  p = curthread->td_proc;
193  FILEDESC_XLOCK(p->p_fd);
194 
195  if (p->p_fd->fd_cdir != NULL)
196  vrele(p->p_fd->fd_cdir);
197  p->p_fd->fd_cdir = rootvnode;
198  VREF(rootvnode);
199 
200  if (p->p_fd->fd_rdir != NULL)
201  vrele(p->p_fd->fd_rdir);
202  p->p_fd->fd_rdir = rootvnode;
203  VREF(rootvnode);
204 
205  FILEDESC_XUNLOCK(p->p_fd);
206 }
207 
208 static int
209 vfs_mountroot_devfs(struct thread *td, struct mount **mpp)
210 {
211  struct vfsoptlist *opts;
212  struct vfsconf *vfsp;
213  struct mount *mp;
214  int error;
215 
216  *mpp = NULL;
217 
218  vfsp = vfs_byname("devfs");
219  KASSERT(vfsp != NULL, ("Could not find devfs by name"));
220  if (vfsp == NULL)
221  return (ENOENT);
222 
223  mp = vfs_mount_alloc(NULLVP, vfsp, "/dev", td->td_ucred);
224 
225  error = VFS_MOUNT(mp);
226  KASSERT(error == 0, ("VFS_MOUNT(devfs) failed %d", error));
227  if (error)
228  return (error);
229 
230  opts = malloc(sizeof(struct vfsoptlist), M_MOUNT, M_WAITOK);
231  TAILQ_INIT(opts);
232  mp->mnt_opt = opts;
233 
234  mtx_lock(&mountlist_mtx);
235  TAILQ_INSERT_HEAD(&mountlist, mp, mnt_list);
236  mtx_unlock(&mountlist_mtx);
237 
238  *mpp = mp;
239  set_rootvnode();
240 
241  error = kern_symlink(td, "/", "dev", UIO_SYSSPACE);
242  if (error)
243  printf("kern_symlink /dev -> / returns %d\n", error);
244 
245  return (error);
246 }
247 
248 static int
249 vfs_mountroot_shuffle(struct thread *td, struct mount *mpdevfs)
250 {
251  struct nameidata nd;
252  struct mount *mporoot, *mpnroot;
253  struct vnode *vp, *vporoot, *vpdevfs;
254  char *fspath;
255  int error;
256 
257  mpnroot = TAILQ_NEXT(mpdevfs, mnt_list);
258 
259  /* Shuffle the mountlist. */
260  mtx_lock(&mountlist_mtx);
261  mporoot = TAILQ_FIRST(&mountlist);
262  TAILQ_REMOVE(&mountlist, mpdevfs, mnt_list);
263  if (mporoot != mpdevfs) {
264  TAILQ_REMOVE(&mountlist, mpnroot, mnt_list);
265  TAILQ_INSERT_HEAD(&mountlist, mpnroot, mnt_list);
266  }
267  TAILQ_INSERT_TAIL(&mountlist, mpdevfs, mnt_list);
268  mtx_unlock(&mountlist_mtx);
269 
270  cache_purgevfs(mporoot);
271  if (mporoot != mpdevfs)
272  cache_purgevfs(mpdevfs);
273 
274  VFS_ROOT(mporoot, LK_EXCLUSIVE, &vporoot);
275 
276  VI_LOCK(vporoot);
277  vporoot->v_iflag &= ~VI_MOUNT;
278  VI_UNLOCK(vporoot);
279  vporoot->v_mountedhere = NULL;
280  mporoot->mnt_flag &= ~MNT_ROOTFS;
281  mporoot->mnt_vnodecovered = NULL;
282  vput(vporoot);
283 
284  /* Set up the new rootvnode, and purge the cache */
285  mpnroot->mnt_vnodecovered = NULL;
286  set_rootvnode();
287  cache_purgevfs(rootvnode->v_mount);
288 
289  if (mporoot != mpdevfs) {
290  /* Remount old root under /.mount or /mnt */
291  fspath = "/.mount";
292  NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
293  fspath, td);
294  error = namei(&nd);
295  if (error) {
296  NDFREE(&nd, NDF_ONLY_PNBUF);
297  fspath = "/mnt";
298  NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
299  fspath, td);
300  error = namei(&nd);
301  }
302  if (!error) {
303  vp = nd.ni_vp;
304  error = (vp->v_type == VDIR) ? 0 : ENOTDIR;
305  if (!error)
306  error = vinvalbuf(vp, V_SAVE, 0, 0);
307  if (!error) {
308  cache_purge(vp);
309  mporoot->mnt_vnodecovered = vp;
310  vp->v_mountedhere = mporoot;
311  strlcpy(mporoot->mnt_stat.f_mntonname,
312  fspath, MNAMELEN);
313  VOP_UNLOCK(vp, 0);
314  } else
315  vput(vp);
316  }
317  NDFREE(&nd, NDF_ONLY_PNBUF);
318 
319  if (error && bootverbose)
320  printf("mountroot: unable to remount previous root "
321  "under /.mount or /mnt (error %d).\n", error);
322  }
323 
324  /* Remount devfs under /dev */
325  NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, "/dev", td);
326  error = namei(&nd);
327  if (!error) {
328  vp = nd.ni_vp;
329  error = (vp->v_type == VDIR) ? 0 : ENOTDIR;
330  if (!error)
331  error = vinvalbuf(vp, V_SAVE, 0, 0);
332  if (!error) {
333  vpdevfs = mpdevfs->mnt_vnodecovered;
334  if (vpdevfs != NULL) {
335  cache_purge(vpdevfs);
336  vpdevfs->v_mountedhere = NULL;
337  vrele(vpdevfs);
338  }
339  mpdevfs->mnt_vnodecovered = vp;
340  vp->v_mountedhere = mpdevfs;
341  VOP_UNLOCK(vp, 0);
342  } else
343  vput(vp);
344  }
345  if (error && bootverbose)
346  printf("mountroot: unable to remount devfs under /dev "
347  "(error %d).\n", error);
348  NDFREE(&nd, NDF_ONLY_PNBUF);
349 
350  if (mporoot == mpdevfs) {
351  vfs_unbusy(mpdevfs);
352  /* Unlink the no longer needed /dev/dev -> / symlink */
353  error = kern_unlink(td, "/dev/dev", UIO_SYSSPACE);
354  if (error && bootverbose)
355  printf("mountroot: unable to unlink /dev/dev "
356  "(error %d)\n", error);
357  }
358 
359  return (0);
360 }
361 
362 /*
363  * Configuration parser.
364  */
365 
366 /* Parser character classes. */
367 #define CC_WHITESPACE -1
368 #define CC_NONWHITESPACE -2
369 
370 /* Parse errors. */
371 #define PE_EOF -1
372 #define PE_EOL -2
373 
374 static __inline int
375 parse_peek(char **conf)
376 {
377 
378  return (**conf);
379 }
380 
381 static __inline void
382 parse_poke(char **conf, int c)
383 {
384 
385  **conf = c;
386 }
387 
388 static __inline void
389 parse_advance(char **conf)
390 {
391 
392  (*conf)++;
393 }
394 
395 static int
396 parse_skipto(char **conf, int mc)
397 {
398  int c, match;
399 
400  while (1) {
401  c = parse_peek(conf);
402  if (c == 0)
403  return (PE_EOF);
404  switch (mc) {
405  case CC_WHITESPACE:
406  match = (c == ' ' || c == '\t' || c == '\n') ? 1 : 0;
407  break;
408  case CC_NONWHITESPACE:
409  if (c == '\n')
410  return (PE_EOL);
411  match = (c != ' ' && c != '\t') ? 1 : 0;
412  break;
413  default:
414  match = (c == mc) ? 1 : 0;
415  break;
416  }
417  if (match)
418  break;
419  parse_advance(conf);
420  }
421  return (0);
422 }
423 
424 static int
425 parse_token(char **conf, char **tok)
426 {
427  char *p;
428  size_t len;
429  int error;
430 
431  *tok = NULL;
432  error = parse_skipto(conf, CC_NONWHITESPACE);
433  if (error)
434  return (error);
435  p = *conf;
436  error = parse_skipto(conf, CC_WHITESPACE);
437  len = *conf - p;
438  *tok = malloc(len + 1, M_TEMP, M_WAITOK | M_ZERO);
439  bcopy(p, *tok, len);
440  return (0);
441 }
442 
443 static void
444 parse_dir_ask_printenv(const char *var)
445 {
446  char *val;
447 
448  val = getenv(var);
449  if (val != NULL) {
450  printf(" %s=%s\n", var, val);
451  freeenv(val);
452  }
453 }
454 
455 static int
456 parse_dir_ask(char **conf)
457 {
458  char name[80];
459  char *mnt;
460  int error;
461 
462  printf("\nLoader variables:\n");
463  parse_dir_ask_printenv("vfs.root.mountfrom");
464  parse_dir_ask_printenv("vfs.root.mountfrom.options");
465 
466  printf("\nManual root filesystem specification:\n");
467  printf(" <fstype>:<device> [options]\n");
468  printf(" Mount <device> using filesystem <fstype>\n");
469  printf(" and with the specified (optional) option list.\n");
470  printf("\n");
471  printf(" eg. ufs:/dev/da0s1a\n");
472  printf(" zfs:tank\n");
473  printf(" cd9660:/dev/acd0 ro\n");
474  printf(" (which is equivalent to: ");
475  printf("mount -t cd9660 -o ro /dev/acd0 /)\n");
476  printf("\n");
477  printf(" ? List valid disk boot devices\n");
478  printf(" . Yield 1 second (for background tasks)\n");
479  printf(" <empty line> Abort manual input\n");
480 
481  do {
482  error = EINVAL;
483  printf("\nmountroot> ");
484  cngets(name, sizeof(name), GETS_ECHO);
485  if (name[0] == '\0')
486  break;
487  if (name[0] == '?' && name[1] == '\0') {
488  printf("\nList of GEOM managed disk devices:\n ");
489  g_dev_print();
490  continue;
491  }
492  if (name[0] == '.' && name[1] == '\0') {
493  pause("rmask", hz);
494  continue;
495  }
496  mnt = name;
497  error = parse_mount(&mnt);
498  if (error == -1)
499  printf("Invalid file system specification.\n");
500  } while (error != 0);
501 
502  return (error);
503 }
504 
505 static int
506 parse_dir_md(char **conf)
507 {
508  struct stat sb;
509  struct thread *td;
510  struct md_ioctl *mdio;
511  char *path, *tok;
512  int error, fd, len;
513 
514  td = curthread;
515 
516  error = parse_token(conf, &tok);
517  if (error)
518  return (error);
519 
520  len = strlen(tok);
521  mdio = malloc(sizeof(*mdio) + len + 1, M_TEMP, M_WAITOK | M_ZERO);
522  path = (void *)(mdio + 1);
523  bcopy(tok, path, len);
524  free(tok, M_TEMP);
525 
526  /* Get file status. */
527  error = kern_stat(td, path, UIO_SYSSPACE, &sb);
528  if (error)
529  goto out;
530 
531  /* Open /dev/mdctl so that we can attach/detach. */
532  error = kern_open(td, "/dev/" MDCTL_NAME, UIO_SYSSPACE, O_RDWR, 0);
533  if (error)
534  goto out;
535 
536  fd = td->td_retval[0];
537  mdio->md_version = MDIOVERSION;
538  mdio->md_type = MD_VNODE;
539 
540  if (root_mount_mddev != -1) {
541  mdio->md_unit = root_mount_mddev;
542  DROP_GIANT();
543  error = kern_ioctl(td, fd, MDIOCDETACH, (void *)mdio);
544  PICKUP_GIANT();
545  /* Ignore errors. We don't care. */
546  root_mount_mddev = -1;
547  }
548 
549  mdio->md_file = (void *)(mdio + 1);
550  mdio->md_options = MD_AUTOUNIT | MD_READONLY;
551  mdio->md_mediasize = sb.st_size;
552  mdio->md_unit = 0;
553  DROP_GIANT();
554  error = kern_ioctl(td, fd, MDIOCATTACH, (void *)mdio);
555  PICKUP_GIANT();
556  if (error)
557  goto out;
558 
559  if (mdio->md_unit > 9) {
560  printf("rootmount: too many md units\n");
561  mdio->md_file = NULL;
562  mdio->md_options = 0;
563  mdio->md_mediasize = 0;
564  DROP_GIANT();
565  error = kern_ioctl(td, fd, MDIOCDETACH, (void *)mdio);
566  PICKUP_GIANT();
567  /* Ignore errors. We don't care. */
568  error = ERANGE;
569  goto out;
570  }
571 
572  root_mount_mddev = mdio->md_unit;
573  printf(MD_NAME "%u attached to %s\n", root_mount_mddev, mdio->md_file);
574 
575  error = kern_close(td, fd);
576 
577  out:
578  free(mdio, M_TEMP);
579  return (error);
580 }
581 
582 static int
583 parse_dir_onfail(char **conf)
584 {
585  char *action;
586  int error;
587 
588  error = parse_token(conf, &action);
589  if (error)
590  return (error);
591 
592  if (!strcmp(action, "continue"))
593  root_mount_onfail = A_CONTINUE;
594  else if (!strcmp(action, "panic"))
595  root_mount_onfail = A_PANIC;
596  else if (!strcmp(action, "reboot"))
597  root_mount_onfail = A_REBOOT;
598  else if (!strcmp(action, "retry"))
599  root_mount_onfail = A_RETRY;
600  else {
601  printf("rootmount: %s: unknown action\n", action);
602  error = EINVAL;
603  }
604 
605  free(action, M_TEMP);
606  return (0);
607 }
608 
609 static int
610 parse_dir_timeout(char **conf)
611 {
612  char *tok, *endtok;
613  long secs;
614  int error;
615 
616  error = parse_token(conf, &tok);
617  if (error)
618  return (error);
619 
620  secs = strtol(tok, &endtok, 0);
621  error = (secs < 0 || *endtok != '\0') ? EINVAL : 0;
622  if (!error)
623  root_mount_timeout = secs;
624  free(tok, M_TEMP);
625  return (error);
626 }
627 
628 static int
629 parse_directive(char **conf)
630 {
631  char *dir;
632  int error;
633 
634  error = parse_token(conf, &dir);
635  if (error)
636  return (error);
637 
638  if (strcmp(dir, ".ask") == 0)
639  error = parse_dir_ask(conf);
640  else if (strcmp(dir, ".md") == 0)
641  error = parse_dir_md(conf);
642  else if (strcmp(dir, ".onfail") == 0)
643  error = parse_dir_onfail(conf);
644  else if (strcmp(dir, ".timeout") == 0)
645  error = parse_dir_timeout(conf);
646  else {
647  printf("mountroot: invalid directive `%s'\n", dir);
648  /* Ignore the rest of the line. */
649  (void)parse_skipto(conf, '\n');
650  error = EINVAL;
651  }
652  free(dir, M_TEMP);
653  return (error);
654 }
655 
656 static int
657 parse_mount_dev_present(const char *dev)
658 {
659  struct nameidata nd;
660  int error;
661 
662  NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, dev, curthread);
663  error = namei(&nd);
664  if (!error)
665  vput(nd.ni_vp);
666  NDFREE(&nd, NDF_ONLY_PNBUF);
667  return (error != 0) ? 0 : 1;
668 }
669 
670 #define ERRMSGL 255
671 static int
672 parse_mount(char **conf)
673 {
674  char *errmsg;
675  struct mntarg *ma;
676  char *dev, *fs, *opts, *tok;
677  int delay, error, timeout;
678 
679  error = parse_token(conf, &tok);
680  if (error)
681  return (error);
682  fs = tok;
683  error = parse_skipto(&tok, ':');
684  if (error) {
685  free(fs, M_TEMP);
686  return (error);
687  }
688  parse_poke(&tok, '\0');
689  parse_advance(&tok);
690  dev = tok;
691 
692  if (root_mount_mddev != -1) {
693  /* Handle substitution for the md unit number. */
694  tok = strstr(dev, "md#");
695  if (tok != NULL)
696  tok[2] = '0' + root_mount_mddev;
697  }
698 
699  /* Parse options. */
700  error = parse_token(conf, &tok);
701  opts = (error == 0) ? tok : NULL;
702 
703  printf("Trying to mount root from %s:%s [%s]...\n", fs, dev,
704  (opts != NULL) ? opts : "");
705 
706  errmsg = malloc(ERRMSGL, M_TEMP, M_WAITOK | M_ZERO);
707 
708  if (vfs_byname(fs) == NULL) {
709  strlcpy(errmsg, "unknown file system", ERRMSGL);
710  error = ENOENT;
711  goto out;
712  }
713 
714  if (strcmp(fs, "zfs") != 0 && dev[0] != '\0' &&
715  !parse_mount_dev_present(dev)) {
716  printf("mountroot: waiting for device %s ...\n", dev);
717  delay = hz / 10;
718  timeout = root_mount_timeout * hz;
719  do {
720  pause("rmdev", delay);
721  timeout -= delay;
722  } while (timeout > 0 && !parse_mount_dev_present(dev));
723  if (timeout <= 0) {
724  error = ENODEV;
725  goto out;
726  }
727  }
728 
729  ma = NULL;
730  ma = mount_arg(ma, "fstype", fs, -1);
731  ma = mount_arg(ma, "fspath", "/", -1);
732  ma = mount_arg(ma, "from", dev, -1);
733  ma = mount_arg(ma, "errmsg", errmsg, ERRMSGL);
734  ma = mount_arg(ma, "ro", NULL, 0);
735  ma = parse_mountroot_options(ma, opts);
736  error = kernel_mount(ma, MNT_ROOTFS);
737 
738  out:
739  if (error) {
740  printf("Mounting from %s:%s failed with error %d",
741  fs, dev, error);
742  if (errmsg[0] != '\0')
743  printf(": %s", errmsg);
744  printf(".\n");
745  }
746  free(fs, M_TEMP);
747  free(errmsg, M_TEMP);
748  if (opts != NULL)
749  free(opts, M_TEMP);
750  /* kernel_mount can return -1 on error. */
751  return ((error < 0) ? EDOOFUS : error);
752 }
753 #undef ERRMSGL
754 
755 static int
756 vfs_mountroot_parse(struct sbuf *sb, struct mount *mpdevfs)
757 {
758  struct mount *mp;
759  char *conf;
760  int error;
761 
762  root_mount_mddev = -1;
763 
764 retry:
765  conf = sbuf_data(sb);
766  mp = TAILQ_NEXT(mpdevfs, mnt_list);
767  error = (mp == NULL) ? 0 : EDOOFUS;
768  root_mount_onfail = A_CONTINUE;
769  while (mp == NULL) {
770  error = parse_skipto(&conf, CC_NONWHITESPACE);
771  if (error == PE_EOL) {
772  parse_advance(&conf);
773  continue;
774  }
775  if (error < 0)
776  break;
777  switch (parse_peek(&conf)) {
778  case '#':
779  error = parse_skipto(&conf, '\n');
780  break;
781  case '.':
782  error = parse_directive(&conf);
783  break;
784  default:
785  error = parse_mount(&conf);
786  break;
787  }
788  if (error < 0)
789  break;
790  /* Ignore any trailing garbage on the line. */
791  if (parse_peek(&conf) != '\n') {
792  printf("mountroot: advancing to next directive...\n");
793  (void)parse_skipto(&conf, '\n');
794  }
795  mp = TAILQ_NEXT(mpdevfs, mnt_list);
796  }
797  if (mp != NULL)
798  return (0);
799 
800  /*
801  * We failed to mount (a new) root.
802  */
803  switch (root_mount_onfail) {
804  case A_CONTINUE:
805  break;
806  case A_PANIC:
807  panic("mountroot: unable to (re-)mount root.");
808  /* NOTREACHED */
809  case A_RETRY:
810  goto retry;
811  case A_REBOOT:
812  kern_reboot(RB_NOSYNC);
813  /* NOTREACHED */
814  }
815 
816  return (error);
817 }
818 
819 static void
820 vfs_mountroot_conf0(struct sbuf *sb)
821 {
822  char *s, *tok, *mnt, *opt;
823  int error;
824 
825  sbuf_printf(sb, ".onfail panic\n");
826  sbuf_printf(sb, ".timeout %d\n", root_mount_timeout);
827  if (boothowto & RB_ASKNAME)
828  sbuf_printf(sb, ".ask\n");
829 #ifdef ROOTDEVNAME
830  if (boothowto & RB_DFLTROOT)
831  sbuf_printf(sb, "%s\n", ROOTDEVNAME);
832 #endif
833  if (boothowto & RB_CDROM) {
834  sbuf_printf(sb, "cd9660:/dev/cd0 ro\n");
835  sbuf_printf(sb, ".timeout 0\n");
836  sbuf_printf(sb, "cd9660:/dev/acd0 ro\n");
837  sbuf_printf(sb, ".timeout %d\n", root_mount_timeout);
838  }
839  s = getenv("vfs.root.mountfrom");
840  if (s != NULL) {
841  opt = getenv("vfs.root.mountfrom.options");
842  tok = s;
843  error = parse_token(&tok, &mnt);
844  while (!error) {
845  sbuf_printf(sb, "%s %s\n", mnt,
846  (opt != NULL) ? opt : "");
847  free(mnt, M_TEMP);
848  error = parse_token(&tok, &mnt);
849  }
850  if (opt != NULL)
851  freeenv(opt);
852  freeenv(s);
853  }
854  if (rootdevnames[0] != NULL)
855  sbuf_printf(sb, "%s\n", rootdevnames[0]);
856  if (rootdevnames[1] != NULL)
857  sbuf_printf(sb, "%s\n", rootdevnames[1]);
858 #ifdef ROOTDEVNAME
859  if (!(boothowto & RB_DFLTROOT))
860  sbuf_printf(sb, "%s\n", ROOTDEVNAME);
861 #endif
862  if (!(boothowto & RB_ASKNAME))
863  sbuf_printf(sb, ".ask\n");
864 }
865 
866 static int
867 vfs_mountroot_readconf(struct thread *td, struct sbuf *sb)
868 {
869  static char buf[128];
870  struct nameidata nd;
871  off_t ofs;
872  ssize_t resid;
873  int error, flags, len, vfslocked;
874 
875  NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE,
876  "/.mount.conf", td);
877  flags = FREAD;
878  error = vn_open(&nd, &flags, 0, NULL);
879  if (error)
880  return (error);
881 
882  vfslocked = NDHASGIANT(&nd);
883  NDFREE(&nd, NDF_ONLY_PNBUF);
884  ofs = 0;
885  len = sizeof(buf) - 1;
886  while (1) {
887  error = vn_rdwr(UIO_READ, nd.ni_vp, buf, len, ofs,
888  UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred,
889  NOCRED, &resid, td);
890  if (error)
891  break;
892  if (resid == len)
893  break;
894  buf[len - resid] = 0;
895  sbuf_printf(sb, "%s", buf);
896  ofs += len - resid;
897  }
898 
899  VOP_UNLOCK(nd.ni_vp, 0);
900  vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
901  VFS_UNLOCK_GIANT(vfslocked);
902  return (error);
903 }
904 
905 static void
907 {
908  struct root_hold_token *h;
909  struct timeval lastfail;
910  int curfail;
911 
912  curfail = 0;
913  while (1) {
914  DROP_GIANT();
915  g_waitidle();
916  PICKUP_GIANT();
917  mtx_lock(&root_holds_mtx);
918  if (LIST_EMPTY(&root_holds)) {
919  mtx_unlock(&root_holds_mtx);
920  break;
921  }
922  if (ppsratecheck(&lastfail, &curfail, 1)) {
923  printf("Root mount waiting for:");
924  LIST_FOREACH(h, &root_holds, list)
925  printf(" %s", h->who);
926  printf("\n");
927  }
928  msleep(&root_holds, &root_holds_mtx, PZERO | PDROP, "roothold",
929  hz);
930  }
931 }
932 
933 void
935 {
936  struct mount *mp;
937  struct sbuf *sb;
938  struct thread *td;
939  time_t timebase;
940  int error;
941 
942  td = curthread;
943 
945 
946  sb = sbuf_new_auto();
948  sbuf_finish(sb);
949 
950  error = vfs_mountroot_devfs(td, &mp);
951  while (!error) {
952  error = vfs_mountroot_parse(sb, mp);
953  if (!error) {
954  error = vfs_mountroot_shuffle(td, mp);
955  if (!error) {
956  sbuf_clear(sb);
957  error = vfs_mountroot_readconf(td, sb);
958  sbuf_finish(sb);
959  }
960  }
961  }
962 
963  sbuf_delete(sb);
964 
965  /*
966  * Iterate over all currently mounted file systems and use
967  * the time stamp found to check and/or initialize the RTC.
968  * Call inittodr() only once and pass it the largest of the
969  * timestamps we encounter.
970  */
971  timebase = 0;
972  mtx_lock(&mountlist_mtx);
973  mp = TAILQ_FIRST(&mountlist);
974  while (mp != NULL) {
975  if (mp->mnt_time > timebase)
976  timebase = mp->mnt_time;
977  mp = TAILQ_NEXT(mp, mnt_list);
978  }
979  mtx_unlock(&mountlist_mtx);
980  inittodr(timebase);
981 
982  /* Keep prison0's root in sync with the global rootvnode. */
983  mtx_lock(&prison0.pr_mtx);
984  prison0.pr_root = rootvnode;
985  vref(prison0.pr_root);
986  mtx_unlock(&prison0.pr_mtx);
987 
988  mtx_lock(&root_holds_mtx);
989  atomic_store_rel_int(&root_mount_complete, 1);
990  wakeup(&root_mount_complete);
991  mtx_unlock(&root_holds_mtx);
992 
993  EVENTHANDLER_INVOKE(mountroot);
994 }
995 
996 static struct mntarg *
997 parse_mountroot_options(struct mntarg *ma, const char *options)
998 {
999  char *p;
1000  char *name, *name_arg;
1001  char *val, *val_arg;
1002  char *opts;
1003 
1004  if (options == NULL || options[0] == '\0')
1005  return (ma);
1006 
1007  p = opts = strdup(options, M_MOUNT);
1008  if (opts == NULL) {
1009  return (ma);
1010  }
1011 
1012  while((name = strsep(&p, ",")) != NULL) {
1013  if (name[0] == '\0')
1014  break;
1015 
1016  val = strchr(name, '=');
1017  if (val != NULL) {
1018  *val = '\0';
1019  ++val;
1020  }
1021  if( strcmp(name, "rw") == 0 ||
1022  strcmp(name, "noro") == 0) {
1023  /*
1024  * The first time we mount the root file system,
1025  * we need to mount 'ro', so We need to ignore
1026  * 'rw' and 'noro' mount options.
1027  */
1028  continue;
1029  }
1030  name_arg = strdup(name, M_MOUNT);
1031  val_arg = NULL;
1032  if (val != NULL)
1033  val_arg = strdup(val, M_MOUNT);
1034 
1035  ma = mount_arg(ma, name_arg, val_arg,
1036  (val_arg != NULL ? -1 : 0));
1037  }
1038  free(opts, M_MOUNT);
1039  return (ma);
1040 }
static int parse_skipto(char **conf, int mc)
static int vfs_mountroot_shuffle(struct thread *td, struct mount *mpdevfs)
int fd
Definition: kern_exec.c:199
struct callout_handle timeout(timeout_t *ftn, void *arg, int to_ticks)
Definition: kern_timeout.c:713
int vinvalbuf(struct vnode *vp, int flags, int slpflag, int slptimeo)
Definition: vfs_subr.c:1348
int kern_close(struct thread *td, int fd)
struct buf * buf
Definition: vfs_bio.c:97
void inittodr(time_t base)
Definition: subr_rtc.c:110
char * path
void NDFREE(struct nameidata *ndp, const u_int flags)
Definition: vfs_lookup.c:1091
#define CC_NONWHITESPACE
static __inline void parse_poke(char **conf, int c)
int ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps)
Definition: kern_time.c:948
void kern_reboot(int howto)
static int root_mount_timeout
void cngets(char *cp, size_t size, int visible)
Definition: kern_cons.c:414
static void vfs_mountroot_conf0(struct sbuf *sb)
int bootverbose
Definition: init_main.c:107
#define ERRMSGL
void * malloc(unsigned long size, struct malloc_type *mtp, int flags)
Definition: kern_malloc.c:454
void cache_purge(struct vnode *vp)
Definition: vfs_cache.c:941
static int parse_dir_onfail(char **conf)
static int root_mount_mddev
__FBSDID("$BSDSUniX$")
static int vfs_mountroot_parse(struct sbuf *sb, struct mount *mpdevfs)
void panic(const char *fmt,...)
static int root_mount_complete
static int parse_dir_ask(char **conf)
static int vfs_mountroot_devfs(struct thread *td, struct mount **mpp)
void freeenv(char *env)
const char * name
Definition: kern_fail.c:97
int boothowto
Definition: init_main.c:104
void root_mount_rel(struct root_hold_token *h)
static LIST_HEAD(root_hold_token)
int error
Definition: vfs_mount.c:1808
int kern_stat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp)
struct vfsconfhead vfsconf
Definition: vfs_init.c:66
static int parse_dir_timeout(char **conf)
static int parse_mount_dev_present(const char *dev)
static void vfs_mountroot_wait(void)
void vref(struct vnode *vp)
Definition: vfs_subr.c:2302
static void set_rootvnode(void)
struct vfsconf * vfs_byname(const char *name)
Definition: vfs_init.c:109
static int parse_dir_md(char **conf)
void vput(struct vnode *vp)
Definition: vfs_subr.c:2428
struct mount * vfs_mount_alloc(struct vnode *vp, struct vfsconf *vfsp, const char *fspath, struct ucred *cred)
Definition: vfs_mount.c:452
void sbuf_clear(struct sbuf *s)
Definition: subr_sbuf.c:269
struct mtx root_holds_mtx
int kern_unlink(struct thread *td, char *path, enum uio_seg pathseg)
void cache_purgevfs(struct mount *mp)
Definition: vfs_cache.c:984
void vfs_unbusy(struct mount *mp)
Definition: vfs_subr.c:442
int kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags, int mode)
static struct mntarg * parse_mountroot_options(struct mntarg *, const char *)
int namei(struct nameidata *ndp)
Definition: vfs_lookup.c:135
int sbuf_printf(struct sbuf *s, const char *fmt,...)
Definition: subr_sbuf.c:632
struct prison prison0
Definition: kern_jail.c:99
struct mntarg * mount_arg(struct mntarg *ma, const char *name, const void *val, int len)
Definition: vfs_mount.c:1900
int kern_ioctl(struct thread *td, int fd, u_long com, caddr_t data)
Definition: sys_generic.c:724
static void parse_dir_ask_printenv(const char *var)
void vfs_mountroot(void)
#define PE_EOF
int vn_rdwr(enum uio_rw rw, struct vnode *vp, void *base, int len, off_t offset, enum uio_seg segflg, int ioflg, struct ucred *active_cred, struct ucred *file_cred, ssize_t *aresid, struct thread *td)
Definition: vfs_vnops.c:379
static int vfs_mountroot_readconf(struct thread *td, struct sbuf *sb)
char * getenv(const char *name)
MTX_SYSINIT(root_holds,&root_holds_mtx,"root_holds", MTX_DEF)
struct mtx mountlist_mtx
Definition: vfs_mount.c:88
static int parse_directive(char **conf)
int kernel_mount(struct mntarg *ma, uint64_t flags)
Definition: vfs_mount.c:1946
int pause(const char *wmesg, int timo)
Definition: kern_synch.c:350
void free(void *addr, struct malloc_type *mtp)
Definition: kern_malloc.c:554
int vn_close(struct vnode *vp, int flags, struct ucred *file_cred, struct thread *td)
Definition: vfs_vnops.c:303
int printf(const char *fmt,...)
Definition: subr_prf.c:367
void sbuf_delete(struct sbuf *s)
Definition: subr_sbuf.c:753
#define PE_EOL
TUNABLE_INT("vfs.mountroot.timeout",&root_mount_timeout)
void wakeup(void *ident)
Definition: kern_synch.c:378
struct mntlist mountlist
Definition: vfs_mount.c:85
void vrele(struct vnode *vp)
Definition: vfs_subr.c:2416
int kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg)
char * sbuf_data(struct sbuf *s)
Definition: subr_sbuf.c:721
void root_mount_wait(void)
int sbuf_finish(struct sbuf *s)
Definition: subr_sbuf.c:694
static int parse_mount(char **)
const char * who
static int parse_token(char **conf, char **tok)
static enum action root_mount_onfail
char * rootdevnames[2]
Definition: vfs_mountroot.c:98
int vn_open(struct nameidata *ndp, int *flagp, int cmode, struct file *fp)
Definition: vfs_vnops.c:106
static __inline void parse_advance(char **conf)
struct vnode * rootvnode
Definition: vfs_mountroot.c:96
static __inline int parse_peek(char **conf)
#define CC_WHITESPACE
struct root_hold_token * root_mount_hold(const char *identifier)
int root_mounted(void)
int hz
Definition: subr_param.c:84