summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/vfs_mountroot.c4
-rw-r--r--sys/nfs/bootp_subr.c73
2 files changed, 56 insertions, 21 deletions
diff --git a/sys/kern/vfs_mountroot.c b/sys/kern/vfs_mountroot.c
index 162738d..57d155b 100644
--- a/sys/kern/vfs_mountroot.c
+++ b/sys/kern/vfs_mountroot.c
@@ -714,8 +714,8 @@ parse_mount(char **conf)
goto out;
}
- if (strcmp(fs, "zfs") != 0 && dev[0] != '\0' &&
- !parse_mount_dev_present(dev)) {
+ if (strcmp(fs, "zfs") != 0 && strstr(fs, "nfs") == NULL &&
+ dev[0] != '\0' && !parse_mount_dev_present(dev)) {
printf("mountroot: waiting for device %s ...\n", dev);
delay = hz / 10;
timeout = root_mount_timeout * hz;
diff --git a/sys/nfs/bootp_subr.c b/sys/nfs/bootp_subr.c
index 2c57a91..7b84f94 100644
--- a/sys/nfs/bootp_subr.c
+++ b/sys/nfs/bootp_subr.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include "opt_bootp.h"
#include "opt_nfs.h"
+#include "opt_rootdevname.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -55,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mount.h>
#include <sys/mbuf.h>
#include <sys/proc.h>
+#include <sys/reboot.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
@@ -167,6 +169,7 @@ struct bootpc_tagcontext {
struct bootpc_globalcontext {
STAILQ_HEAD(, bootpc_ifcontext) interfaces;
u_int32_t xid;
+ int any_root_overrides;
int gotrootpath;
int gotgw;
int ifnum;
@@ -865,13 +868,14 @@ bootpc_call(struct bootpc_globalcontext *gctx, struct thread *td)
BOOTP_SETTLE_DELAY;
} else
printf(" (ignored)");
- if (ifctx->gotrootpath) {
+ if (ifctx->gotrootpath ||
+ gctx->any_root_overrides) {
gotrootpath = 1;
rtimo = time_second +
BOOTP_SETTLE_DELAY;
- printf(" (got root path)");
- } else
- printf(" (no root path)");
+ if (ifctx->gotrootpath)
+ printf(" (got root path)");
+ }
printf("\n");
}
} /* while secs */
@@ -1371,7 +1375,7 @@ static void
bootpc_decode_reply(struct nfsv3_diskless *nd, struct bootpc_ifcontext *ifctx,
struct bootpc_globalcontext *gctx)
{
- char *p;
+ char *p, *s;
unsigned int ip;
ifctx->gotgw = 0;
@@ -1438,8 +1442,30 @@ bootpc_decode_reply(struct nfsv3_diskless *nd, struct bootpc_ifcontext *ifctx,
}
}
- p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
+ /*
+ * Choose a root filesystem. If a value is forced in the environment
+ * and it contains "nfs:", use it unconditionally. Otherwise, if the
+ * kernel is compiled with the ROOTDEVNAME option, then use it if:
+ * - The server doesn't provide a pathname.
+ * - The boothowto flags include RB_DFLTROOT (user said to override
+ * the server value).
+ */
+ p = NULL;
+ if ((s = getenv("vfs.root.mountfrom")) != NULL) {
+ if ((p = strstr(s, "nfs:")) != NULL)
+ p = strdup(p + 4, M_TEMP);
+ freeenv(s);
+ }
+ if (p == NULL) {
+ p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
TAG_ROOT);
+ }
+#ifdef ROOTDEVNAME
+ if ((p == NULL || (boothowto & RB_DFLTROOT) != 0) &&
+ (p = strstr(ROOTDEVNAME, "nfs:")) != NULL) {
+ p += 4;
+ }
+#endif
if (p != NULL) {
if (gctx->setrootfs != NULL) {
printf("rootfs %s (ignored) ", p);
@@ -1544,6 +1570,17 @@ bootpc_init(void)
gctx->starttime = time_second;
/*
+ * If ROOTDEVNAME is defined or vfs.root.mountfrom is set then we have
+ * root-path overrides that can potentially let us boot even if we don't
+ * get a root path from the server, so we can treat that as a non-error.
+ */
+#ifdef ROOTDEVNAME
+ gctx->any_root_overrides = 1;
+#else
+ gctx->any_root_overrides = testenv("vfs.root.mountfrom");
+#endif
+
+ /*
* Find a network interface.
*/
CURVNET_SET(TD_TO_VNET(td));
@@ -1652,19 +1689,10 @@ retry:
bootpc_compose_query(ifctx, td);
error = bootpc_call(gctx, td);
-
if (error != 0) {
-#ifdef BOOTP_NFSROOT
- panic("BOOTP call failed");
-#else
printf("BOOTP call failed\n");
-#endif
}
- rootdevnames[0] = "nfs:";
-#ifdef NFSCLIENT
- rootdevnames[1] = "oldnfs:";
-#endif
mountopts(&nd->root_args, NULL);
STAILQ_FOREACH(ifctx, &gctx->interfaces, next)
@@ -1672,7 +1700,7 @@ retry:
bootpc_decode_reply(nd, ifctx, gctx);
#ifdef BOOTP_NFSROOT
- if (gctx->gotrootpath == 0)
+ if (gctx->gotrootpath == 0 && gctx->any_root_overrides == 0)
panic("bootpc: No root path offered");
#endif
@@ -1699,9 +1727,16 @@ retry:
error = md_mount(&nd->root_saddr, nd->root_hostnam,
nd->root_fh, &nd->root_fhsize,
&nd->root_args, td);
- if (error != 0)
- panic("nfs_boot: mountd root, error=%d", error);
-
+ if (error != 0) {
+ if (gctx->any_root_overrides == 0)
+ panic("nfs_boot: mount root, error=%d", error);
+ else
+ goto out;
+ }
+ rootdevnames[0] = "nfs:";
+#ifdef NFSCLIENT
+ rootdevnames[1] = "oldnfs:";
+#endif
nfs_diskless_valid = 3;
}
OpenPOWER on IntegriCloud