Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F163991720
D5522.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D5522.diff
View Options
Index: sys/boot/common/boot.c
===================================================================
--- sys/boot/common/boot.c
+++ sys/boot/common/boot.c
@@ -31,11 +31,14 @@
* Loading modules, booting the system
*/
+#include <sys/disk.h>
+
#include <stand.h>
#include <string.h>
#include "bootstrap.h"
+static int announce_boot_intent(void);
static char *getbootfile(int try);
static int loadakernel(int try, int argc, char* argv[]);
@@ -55,6 +58,11 @@
struct preloaded_file *fp;
/*
+ * Inform the device that we're about to boot.
+ */
+ announce_boot_intent();
+
+ /*
* See if the user has specified an explicit kernel to boot.
*/
if ((argc > 1) && (argv[1][0] != '-')) {
@@ -162,6 +170,7 @@
int c, yes;
char *argv[2], *cp, *ep;
char *kernelname;
+ char *kernel_other_nfs;
#ifdef BOOT_PROMPT_123
const char *seq = "123", *p = seq;
#endif
@@ -178,6 +187,25 @@
}
}
+ /* See if we are asked to swap NFS handle early. */
+ kernel_other_nfs = getenv("kernel_other_nfs");
+ if (kernel_other_nfs != NULL) {
+ announce_boot_intent();
+
+ /*
+ * If we were triggered to do this. Try to re-start, which we
+ * cannot easily, thus just re-read the config file(s) from the
+ * new location and cross our fingers.
+ */
+ /*
+ * Read our default configuration
+ */
+ if (include("/boot/loader.rc") != CMD_OK)
+ include("/boot/boot.conf");
+ printf("\n");
+
+ }
+
kernelname = getenv("kernelname");
if (kernelname == NULL) {
argv[0] = NULL;
@@ -395,6 +423,31 @@
}
static int
+announce_boot_intent(void)
+{
+ struct devdesc *dev;
+ int result;
+ const char *currdev;
+ const char *rootpath; /* ignored */
+
+ /*
+ * Send a 'flush write cache' ioctl to the boot device.
+ * PXE will interpret this as "ensure your NFS handle matches
+ * 'vfs.root.mountfrom', if one is set".
+ */
+
+ currdev = getenv("currdev");
+ if (currdev == NULL)
+ return (0);
+
+ result = archsw.arch_getdev((void **)&dev, currdev, &rootpath);
+ if (result)
+ return (result);
+
+ return dev->d_dev->dv_ioctl(NULL, DIOCGFLUSH, NULL);
+}
+
+static int
loadakernel(int try, int argc, char* argv[])
{
char *cp;
Index: sys/boot/i386/libi386/pxe.c
===================================================================
--- sys/boot/i386/libi386/pxe.c
+++ sys/boot/i386/libi386/pxe.c
@@ -29,6 +29,9 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/disk.h>
+
+#include <assert.h>
#include <stand.h>
#include <string.h>
#include <stdarg.h>
@@ -75,6 +78,7 @@
size_t size, char *buf, size_t *rsize);
static int pxe_open(struct open_file *f, ...);
static int pxe_close(struct open_file *f);
+static int pxe_ioctl(struct open_file *f, u_long cmd, void *data);
static void pxe_print(int verbose);
static void pxe_cleanup(void);
static void pxe_setnfshandle(char *rootpath);
@@ -88,6 +92,14 @@
static int pxe_netif_put(struct iodesc *desc, void *pkt, size_t len);
static void pxe_netif_end(struct netif *nif);
+#ifdef LOADER_NFS_SUPPORT
+extern int rpc_port;
+static int pxe_compareroot(const in_addr_t addr0, const char *path0,
+ const in_addr_t addr1, const char *path1);
+static int pxe_pivot_nfsroot(const char *mountspec);
+static void pxe_rpcmountcall(void);
+#endif
+
#ifdef OLD_NFSV2
int nfs_getrootfh(struct iodesc*, char*, u_char*);
#else
@@ -133,7 +145,7 @@
pxe_strategy,
pxe_open,
pxe_close,
- noioctl,
+ pxe_ioctl,
pxe_print,
pxe_cleanup
};
@@ -358,6 +370,121 @@
return (0);
}
+static int
+pxe_ioctl(struct open_file *f, u_long cmd, void *data)
+{
+#ifdef LOADER_NFS_SUPPORT
+ /*
+ * If we receive the 'flush your write cache' ioctl, check for a
+ * mismatch between boot.nfsroot.* and vfs.root.mountfrom.
+ *
+ * We may need to pivot from the NFS boot directory to a different
+ * NFS root directory.
+ */
+ if (cmd == DIOCGFLUSH)
+ return pxe_pivot_nfsroot(getenv("vfs.root.mountfrom"));
+#endif
+
+ return (0);
+}
+
+#ifdef LOADER_NFS_SUPPORT
+static int
+pxe_pivot_nfsroot(const char *mountspec)
+{
+ static const char NFS_PREFIX[] = "nfs:";
+
+ /*
+ * This function should only be called after all boot files have been
+ * loaded and the PXE TFTP stack has been shut down.
+ */
+ assert(pxe_opens == 0);
+ assert(pxe_sock == -1);
+
+ /*
+ * Ignore all mountfrom specifications that aren't NFS; the kernel
+ * can handle them without loader assistance.
+ */
+ if (mountspec == NULL)
+ return (0);
+
+ if (strncmp(mountspec, NFS_PREFIX, sizeof(NFS_PREFIX) - 1) != 0) {
+#ifdef PXE_DEBUG
+ if (pxe_debug)
+ printf("pxe_pivot_nfsroot: ignoring non-NFS root '%s'\n",
+ mountspec);
+#endif
+ return (0);
+ }
+
+ /* Ignore the 'nfs:' prefix; we know that we're doing NFS. */
+ mountspec += sizeof(NFS_PREFIX) - 1;
+
+
+ /*
+ * Compare the current root with vfs.root.mountfrom.
+ * If they're the same, there's no need to pivot.
+ */
+ struct in_addr next_ip = { .s_addr = 0 };
+ const char *next_path;
+
+ for (int i = 0; i < FNAME_SIZE; i++)
+ if (mountspec[i] == ':') {
+ /* inet_addr() needs a null-terminated string. */
+ char addr[i + 1];
+ bcopy(mountspec, addr, i);
+ addr[i] = '\0';
+
+ next_ip.s_addr = inet_addr(addr);
+ next_path = mountspec + i + 1;
+ break;
+ }
+
+ if (next_ip.s_addr == 0) {
+ printf("NFS MOUNT ERROR: NFS root '%s' does not contain ':'\n",
+ mountspec);
+ return (EINVAL);
+ }
+
+ if (pxe_compareroot(rootip.s_addr, rootpath,
+ next_ip.s_addr, next_path) == 0)
+ return (0);
+
+
+ /*
+ * Do the pivot to the root filesystem.
+ */
+ printf("pxe_pivot_nfsroot:\n");
+ printf(" boot %s:%s\n", inet_ntoa(rootip), rootpath);
+ printf(" root %s:%s\n", inet_ntoa(next_ip), next_path);
+
+ /*
+ * pxe_setnfshandle ignores its argument: it uses the global
+ * 'rootip' and 'rootpath' variables.
+ */
+ rootip = next_ip;
+ strncpy(rootpath, next_path, FNAME_SIZE);
+
+ pxe_sock = netif_open(NULL);
+
+ pxe_rpcmountcall();
+ pxe_setnfshandle(NULL);
+ setenv("boot.nfsroot.path", next_path, 1);
+ setenv("boot.nfsroot.server", inet_ntoa(next_ip), 1);
+ setenv("dhcp.root-path", mountspec, 1);
+
+ netif_close(pxe_sock);
+ pxe_sock = -1;
+
+#ifdef PXE_DEBUG
+ if (pxe_debug)
+ pxe_print(0);
+#endif
+
+ return (0);
+}
+#endif /* LOADER_NFS_SUPPORT */
+
static void
pxe_print(int verbose)
{
@@ -417,7 +544,6 @@
/* structure truncated here */
};
extern struct nfs_iodesc nfs_root_node;
-extern int rpc_port;
static void
pxe_rpcmountcall()
@@ -469,7 +595,6 @@
/* structure truncated */
};
extern struct nfs_iodesc nfs_root_node;
-extern int rpc_port;
static void
pxe_rpcmountcall()
@@ -477,8 +602,10 @@
struct iodesc *d;
int error;
- if (!(d = socktodesc(pxe_sock)))
+ if (!(d = socktodesc(pxe_sock))) {
+ printf("NFS MOUNT ERROR: no PXE socket %d\n", pxe_sock);
return;
+ }
d->myport = htons(--rpc_port);
d->destip = rootip;
if ((error = nfs_getrootfh(d, rootpath, &nfs_root_node.fhsize,
@@ -515,6 +642,19 @@
setenv("boot.nfsroot.nfshandlelen", buf, 1);
}
#endif /* OLD_NFSV2 */
+
+
+static int
+pxe_compareroot(const in_addr_t addr0, const char *path0,
+ const in_addr_t addr1, const char *path1)
+{
+ in_addr_t diff = addr0 - addr1;
+
+ if (diff != 0)
+ return diff;
+
+ return strncmp(path0, path1, FNAME_SIZE);
+}
#endif /* LOADER_NFS_SUPPORT */
void
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Jul 28, 5:05 PM (10 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35622764
Default Alt Text
D5522.diff (7 KB)
Attached To
Mode
D5522: Chain-loading loader or re-loading loader.conf
Attached
Detach File
Event Timeline
Log In to Comment