Re: svn commit: r287964 - in head: lib/libc/sys sys/kern sys/sys

2015-09-18 Thread Craig Rodrigues
On Fri, Sep 18, 2015 at 10:32 AM, Edward Tomasz Napierala  wrote:

>   pretty.  The reason for this is to avoid changing vfs_mountroot(), which
>   is (obviously) rather mission-critical, but not very well documented,
>   and thus hard to test properly.
>

vfs_mounroot() is indeed quite involved.  It's not perfect,
but I took an initial pass at writing the mount.conf(8) man page,
which tries to document some stuff.

--
Craig
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r287964 - in head: lib/libc/sys sys/kern sys/sys

2015-09-18 Thread Edward Tomasz Napierala
Author: trasz
Date: Fri Sep 18 17:32:22 2015
New Revision: 287964
URL: https://svnweb.freebsd.org/changeset/base/287964

Log:
  Kernel part of reroot support - a way to change rootfs without reboot.
  
  Note that the mountlist manipulations are somewhat fragile, and not very
  pretty.  The reason for this is to avoid changing vfs_mountroot(), which
  is (obviously) rather mission-critical, but not very well documented,
  and thus hard to test properly.  It might be possible to rework it to use
  its own simple root mount mechanism instead of vfs_mountroot().
  
  Reviewed by:  kib@
  MFC after:1 month
  Sponsored by: The FreeBSD Foundation
  Differential Revision:https://reviews.freebsd.org/D2698

Modified:
  head/lib/libc/sys/reboot.2
  head/sys/kern/kern_shutdown.c
  head/sys/kern/vfs_mountroot.c
  head/sys/sys/reboot.h

Modified: head/lib/libc/sys/reboot.2
==
--- head/lib/libc/sys/reboot.2  Fri Sep 18 17:29:24 2015(r287963)
+++ head/lib/libc/sys/reboot.2  Fri Sep 18 17:32:22 2015(r287964)
@@ -113,6 +113,13 @@ Normally, the disks are sync'd (see
 before the processor is halted or rebooted.
 This option may be useful if file system changes have been made manually
 or if the processor is on fire.
+.It Dv RB_REROOT
+Instead of rebooting, unmount all filesystems except the one containing
+currently-running executable, and mount root filesystem using the same
+mechanism which is used during normal boot, based on
+vfs.root.mountfrom
+.Xr kenv 8
+variable.
 .It Dv RB_RDONLY
 Initially mount the root file system read-only.
 This is currently the default, and this option has been deprecated.

Modified: head/sys/kern/kern_shutdown.c
==
--- head/sys/kern/kern_shutdown.c   Fri Sep 18 17:29:24 2015
(r287963)
+++ head/sys/kern/kern_shutdown.c   Fri Sep 18 17:32:22 2015
(r287964)
@@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -150,10 +151,16 @@ static struct dumperinfo dumper;  /* our 
 static struct pcb dumppcb; /* Registers. */
 lwpid_t dumptid;   /* Thread ID. */
 
+static struct cdevsw reroot_cdevsw = {
+ .d_version = D_VERSION,
+ .d_name= "reroot",
+};
+
 static void poweroff_wait(void *, int);
 static void shutdown_halt(void *junk, int howto);
 static void shutdown_panic(void *junk, int howto);
 static void shutdown_reset(void *junk, int howto);
+static int kern_reroot(void);
 
 /* register various local shutdown events */
 static void
@@ -173,6 +180,26 @@ shutdown_conf(void *unused)
 SYSINIT(shutdown_conf, SI_SUB_INTRINSIC, SI_ORDER_ANY, shutdown_conf, NULL);
 
 /*
+ * The only reason this exists is to create the /dev/reroot/ directory,
+ * used by reroot code in init(8) as a mountpoint for tmpfs.
+ */
+static void
+reroot_conf(void *unused)
+{
+   int error;
+   struct cdev *cdev;
+
+   error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK, ,
+   _cdevsw, NULL, UID_ROOT, GID_WHEEL, 0600, "reroot/reroot");
+   if (error != 0) {
+   printf("%s: failed to create device node, error %d",
+   __func__, error);
+   }
+}
+
+SYSINIT(reroot_conf, SI_SUB_DEVFS, SI_ORDER_ANY, reroot_conf, NULL);
+
+/*
  * The system call that results in a reboot.
  */
 /* ARGSUSED */
@@ -188,9 +215,13 @@ sys_reboot(struct thread *td, struct reb
if (error == 0)
error = priv_check(td, PRIV_REBOOT);
if (error == 0) {
-   mtx_lock();
-   kern_reboot(uap->opt);
-   mtx_unlock();
+   if (uap->opt & RB_REROOT) {
+   error = kern_reroot();
+   } else {
+   mtx_lock();
+   kern_reboot(uap->opt);
+   mtx_unlock();
+   }
}
return (error);
 }
@@ -336,6 +367,102 @@ kern_reboot(int howto)
 }
 
 /*
+ * The system call that results in changing the rootfs.
+ */
+static int
+kern_reroot(void)
+{
+   struct vnode *oldrootvnode, *vp;
+   struct mount *mp, *devmp;
+   int error;
+
+   if (curproc != initproc)
+   return (EPERM);
+
+   /*
+* Mark the filesystem containing currently-running executable
+* (the temporary copy of init(8)) busy.
+*/
+   vp = curproc->p_textvp;
+   error = vn_lock(vp, LK_SHARED);
+   if (error != 0)
+   return (error);
+   mp = vp->v_mount;
+   error = vfs_busy(mp, MBF_NOWAIT);
+   if (error != 0) {
+   vfs_ref(mp);
+   VOP_UNLOCK(vp, 0);
+   error = vfs_busy(mp, 0);
+   vn_lock(vp, LK_SHARED | LK_RETRY);
+   vfs_rel(mp);
+   if (error != 0) {
+   VOP_UNLOCK(vp, 0);
+