Page MenuHomeFreeBSD

D30848.id93659.diff
No OneTemporary

D30848.id93659.diff

Index: stand/efi/libefi/devicename.c
===================================================================
--- stand/efi/libefi/devicename.c
+++ stand/efi/libefi/devicename.c
@@ -31,6 +31,7 @@
#include <stand.h>
#include <string.h>
#include <sys/disklabel.h>
+#include <sys/mount.h>
#include <sys/param.h>
#include <bootstrap.h>
#include <disk.h>
@@ -209,8 +210,18 @@
rv = efi_parsedev(&ncurr, value, NULL);
if (rv != 0)
return (rv);
-
free(ncurr);
- env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
- return (0);
+
+ /* mount new rootfs */
+ rv = mount(value, "/", 0, NULL);
+ if (rv == 0) {
+ /*
+ * Note we unmount only after successful mount because
+ * we do not want to end up without rootfs.
+ */
+ if (ev->ev_value != NULL)
+ unmount(ev->ev_value, 0);
+ env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
+ }
+ return (rv);
}
Index: stand/efi/loader/main.c
===================================================================
--- stand/efi/loader/main.c
+++ stand/efi/loader/main.c
@@ -187,15 +187,12 @@
set_currdev(const char *devname)
{
+ env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
+ env_nounset);
/*
- * Don't execute hooks here; we may need to try setting these more than
- * once here if we're probing for the ZFS pool we're supposed to boot.
- * The currdev hook is intended to just validate user input anyways,
- * while the loaddev hook makes it immutable once we've determined what
- * the proper currdev is.
+ * Don't execute hook here;the loaddev hook makes it immutable
+ * once we've determined what the proper currdev is.
*/
- env_setenv("currdev", EV_VOLATILE | EV_NOHOOK, devname, efi_setcurrdev,
- env_nounset);
env_setenv("loaddev", EV_VOLATILE | EV_NOHOOK, devname, env_noset,
env_nounset);
}
Index: stand/i386/libi386/devicename.c
===================================================================
--- stand/i386/libi386/devicename.c
+++ stand/i386/libi386/devicename.c
@@ -29,6 +29,7 @@
#include <stand.h>
#include <string.h>
+#include <sys/mount.h>
#include "bootstrap.h"
#include "disk.h"
#include "libi386.h"
@@ -204,12 +205,23 @@
int
i386_setcurrdev(struct env_var *ev, int flags, const void *value)
{
- struct i386_devdesc *ncurr;
- int rv;
-
- if ((rv = i386_parsedev(&ncurr, value, NULL)) != 0)
- return(rv);
- free(ncurr);
- env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
- return(0);
+ struct i386_devdesc *ncurr;
+ int rv;
+
+ if ((rv = i386_parsedev(&ncurr, value, NULL)) != 0)
+ return (rv);
+
+ free(ncurr);
+ /* mount new rootfs */
+ rv = mount(value, "/", 0, NULL);
+ if (rv == 0) {
+ /*
+ * Note we unmount only after successful mount because
+ * we do not want to end up without rootfs.
+ */
+ if (ev->ev_value != NULL)
+ unmount(ev->ev_value, 0);
+ env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
+ }
+ return (rv);
}
Index: stand/libofw/devicename.c
===================================================================
--- stand/libofw/devicename.c
+++ stand/libofw/devicename.c
@@ -134,13 +134,24 @@
int
ofw_setcurrdev(struct env_var *ev, int flags, const void *value)
{
- struct ofw_devdesc *ncurr;
- int rv;
+ struct ofw_devdesc *ncurr;
+ int rv;
- if ((rv = ofw_parsedev(&ncurr, value, NULL)) != 0)
- return rv;
+ if ((rv = ofw_parsedev(&ncurr, value, NULL)) != 0)
+ return (rv);
- free(ncurr);
- env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
- return 0;
+ free(ncurr);
+
+ /* mount new rootfs */
+ rv = mount(value, "/", 0, NULL);
+ if (rv == 0) {
+ /*
+ * Note we unmount only after successful mount because
+ * we do not want to end up without rootfs.
+ */
+ if (ev->ev_value != NULL)
+ unmount(ev->ev_value, 0);
+ env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
+ }
+ return (rv);
}
Index: stand/libsa/Makefile
===================================================================
--- stand/libsa/Makefile
+++ stand/libsa/Makefile
@@ -131,7 +131,7 @@
CLEANFILES+= ${SAFE_INCS} ${STAND_H_INC} ${OTHER_INC}
# io routines
-SRCS+= closeall.c dev.c ioctl.c nullfs.c stat.c \
+SRCS+= closeall.c dev.c ioctl.c nullfs.c stat.c mount.c \
fstat.c close.c lseek.c open.c read.c write.c readdir.c
# SMBios routines
Index: stand/libsa/mount.c
===================================================================
--- /dev/null
+++ stand/libsa/mount.c
@@ -0,0 +1,139 @@
+/*-
+ * Copyright 2021 Toomas Soome <tsoome@me.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stand.h>
+#include <sys/queue.h>
+
+/*
+ * While setting "currdev" environment variable, alse "mount" the
+ * new root file system. This is done to hold disk device open
+ * in between file accesses, and thus preserve block cache for
+ * this device. Additionally, this allows us to optimize filesystem
+ * access by sharing filesystem metadata (like superblock).
+ */
+
+typedef STAILQ_HEAD(mnt_info_list, mnt_info) mnt_info_list_t;
+
+typedef struct mnt_info {
+ STAILQ_ENTRY(mnt_info) mnt_link; /* link in mount list */
+ const struct fs_ops *mnt_fs;
+ char *mnt_dev;
+ char *mnt_path;
+ void *mnt_data; /* Private state */
+} mnt_info_t;
+
+/* list of mounted filesystems. */
+static mnt_info_list_t mnt_list = STAILQ_HEAD_INITIALIZER(mnt_list);
+
+static void
+free_mnt(mnt_info_t *mnt)
+{
+ free(mnt->mnt_dev);
+ free(mnt->mnt_path);
+ free(mnt);
+}
+
+static int
+add_mnt_info(struct fs_ops *fs, const char *dev, const char *path, void *data)
+{
+ mnt_info_t *mnt;
+
+ mnt = malloc(sizeof(*mnt));
+ if (mnt == NULL)
+ return (ENOMEM);
+
+ mnt->mnt_fs = fs;
+ mnt->mnt_dev = strdup(dev);
+ mnt->mnt_path = strdup(path);
+ mnt->mnt_data = data;
+
+ if (mnt->mnt_dev == NULL || mnt->mnt_path == NULL) {
+ free_mnt(mnt);
+ return (ENOMEM);
+ }
+ STAILQ_INSERT_TAIL(&mnt_list, mnt, mnt_link);
+ return (0);
+}
+
+static void
+delete_mnt_info(mnt_info_t *mnt)
+{
+ STAILQ_REMOVE(&mnt_list, mnt, mnt_info, mnt_link);
+ free_mnt(mnt);
+}
+
+int
+mount(const char *dev, const char *path, int flag, void *data)
+{
+ mnt_info_t *mnt;
+ int rc = -1;
+
+ /* Is it already mounted? */
+ STAILQ_FOREACH(mnt, &mnt_list, mnt_link) {
+ if (strcmp(dev, mnt->mnt_dev) == 0 &&
+ strcmp(path, mnt->mnt_path) == 0)
+ return (0);
+ }
+
+ for (int i = 0; file_system[i] != NULL; i++) {
+ struct fs_ops *fs;
+
+ fs = file_system[i];
+ if (fs->fo_mount != NULL) {
+ void *data = NULL;
+
+ rc = fs->fo_mount(dev, path, &data);
+ if (rc != 0)
+ continue;
+ rc = add_mnt_info(fs, dev, path, data);
+ break;
+ }
+ }
+
+ if (rc == -1)
+ printf("Unknown or no file system on: %s", dev);
+ rc = 0;
+ return (rc);
+}
+
+int
+unmount(const char *dev, int flag)
+{
+ mnt_info_t *mnt;
+
+ STAILQ_FOREACH(mnt, &mnt_list, mnt_link) {
+ if (strcmp(dev, mnt->mnt_dev) == 0) {
+ if (mnt->mnt_fs->fo_unmount != NULL)
+ mnt->mnt_fs->fo_unmount(dev, mnt->mnt_data);
+ delete_mnt_info(mnt);
+ break;
+ }
+ }
+
+ return (0);
+}
Index: stand/libsa/stand.h
===================================================================
--- stand/libsa/stand.h
+++ stand/libsa/stand.h
@@ -111,6 +111,8 @@
off_t (*fo_seek)(struct open_file *f, off_t offset, int where);
int (*fo_stat)(struct open_file *f, struct stat *sb);
int (*fo_readdir)(struct open_file *f, struct dirent *d);
+ int (*fo_mount)(const char *, const char *, void **);
+ int (*fo_unmount)(const char *, void *);
};
/*
Index: stand/libsa/ufs.c
===================================================================
--- stand/libsa/ufs.c
+++ stand/libsa/ufs.c
@@ -81,6 +81,7 @@
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
#include "stand.h"
+#include "disk.h"
#include "string.h"
static int ufs_open(const char *path, struct open_file *f);
@@ -91,16 +92,20 @@
static off_t ufs_seek(struct open_file *f, off_t offset, int where);
static int ufs_stat(struct open_file *f, struct stat *sb);
static int ufs_readdir(struct open_file *f, struct dirent *d);
+static int ufs_mount(const char *dev, const char *path, void **data);
+static int ufs_unmount(const char *dev, void *data);
struct fs_ops ufs_fsops = {
- "ufs",
- ufs_open,
- ufs_close,
- ufs_read,
- ufs_write,
- ufs_seek,
- ufs_stat,
- ufs_readdir
+ .fs_name = "ufs",
+ .fo_open = ufs_open,
+ .fo_close = ufs_close,
+ .fo_read = ufs_read,
+ .fo_write = ufs_write,
+ .fo_seek = ufs_seek,
+ .fo_stat = ufs_stat,
+ .fo_readdir = ufs_readdir,
+ .fo_mount = ufs_mount,
+ .fo_unmount = ufs_unmount
};
/*
@@ -130,6 +135,15 @@
((fp)->f_fs->fs_magic == FS_UFS1_MAGIC ? \
(fp)->f_di.di1.field : (fp)->f_di.di2.field)
+typedef struct ufs_mnt {
+ char *um_dev;
+ int um_fd;
+ STAILQ_ENTRY(ufs_mnt) um_link;
+} ufs_mnt_t;
+
+typedef STAILQ_HEAD(ufs_mnt_list, ufs_mnt) ufs_mnt_list_t;
+static ufs_mnt_list_t mnt_list = STAILQ_HEAD_INITIALIZER(mnt_list);
+
static int read_inode(ino_t, struct open_file *);
static int block_map(struct open_file *, ufs2_daddr_t, ufs2_daddr_t *);
static int buf_read_file(struct open_file *, char **, size_t *);
@@ -502,9 +516,7 @@
* Open a file.
*/
static int
-ufs_open(upath, f)
- const char *upath;
- struct open_file *f;
+ufs_open(const char *upath, struct open_file *f)
{
char *cp, *ncp;
int c;
@@ -516,18 +528,37 @@
char namebuf[MAXPATHLEN+1];
char *buf = NULL;
char *path = NULL;
+ const char *dev;
+ ufs_mnt_t *mnt;
/* allocate file system specific data structure */
fp = malloc(sizeof(struct file));
bzero(fp, sizeof(struct file));
f->f_fsdata = (void *)fp;
- /* read super block */
- twiddle(1);
- if ((rc = ffs_sbget(f, &fs, STDSB_NOHASHFAIL, "stand",
- ufs_use_sa_read)) != 0)
- goto out;
+ dev = disk_fmtdev(f->f_devdata);
+ STAILQ_FOREACH(mnt, &mnt_list, um_link) {
+ if (strcmp(dev, mnt->um_dev) == 0)
+ break;
+ }
+
+ if (mnt == NULL) {
+ /* read super block */
+ twiddle(1);
+ if ((rc = ffs_sbget(f, &fs, STDSB_NOHASHFAIL, "stand",
+ ufs_use_sa_read)) != 0)
+ goto out;
+ } else {
+ struct open_file *sbf;
+ struct file *sfp;
+
+ /* get superblock from mounted file system */
+ sbf = fd2open_file(mnt->um_fd);
+ sfp = sbf->f_fsdata;
+ fs = sfp->f_fs;
+ }
fp->f_fs = fs;
+
/*
* Calculate indirect block levels.
*/
@@ -671,14 +702,12 @@
rc = 0;
fp->f_seekp = 0;
out:
- if (buf)
- free(buf);
- if (path)
- free(path);
+ free(buf);
+ free(path);
if (rc) {
- if (fp->f_buf)
- free(fp->f_buf);
- if (fp->f_fs != NULL) {
+ free(fp->f_buf);
+
+ if (mnt == NULL && fp->f_fs != NULL) {
free(fp->f_fs->fs_csp);
free(fp->f_fs->fs_si);
free(fp->f_fs);
@@ -714,24 +743,32 @@
ufs_close(f)
struct open_file *f;
{
+ ufs_mnt_t *mnt;
struct file *fp = (struct file *)f->f_fsdata;
int level;
+ char *dev;
- f->f_fsdata = (void *)0;
- if (fp == (struct file *)0)
+ f->f_fsdata = NULL;
+ if (fp == NULL)
return (0);
for (level = 0; level < UFS_NIADDR; level++) {
- if (fp->f_blk[level])
- free(fp->f_blk[level]);
+ free(fp->f_blk[level]);
}
- if (fp->f_buf)
- free(fp->f_buf);
- if (fp->f_fs != NULL) {
+ free(fp->f_buf);
+
+ dev = disk_fmtdev(f->f_devdata);
+ STAILQ_FOREACH(mnt, &mnt_list, um_link) {
+ if (strcmp(dev, mnt->um_dev) == 0)
+ break;
+ }
+
+ if (mnt == NULL && fp->f_fs != NULL) {
free(fp->f_fs->fs_csp);
free(fp->f_fs->fs_si);
free(fp->f_fs);
}
+
free(fp);
return (0);
}
@@ -894,3 +931,52 @@
strcpy(d->d_name, dp->d_name);
return (0);
}
+
+static int
+ufs_mount(const char *dev, const char *path, void **data)
+{
+ char *fs;
+ int fd = -1;
+ ufs_mnt_t *mnt;
+
+ mnt = calloc(1, sizeof(*mnt));
+ if (mnt == NULL)
+ return (errno);
+ mnt->um_fd = -1;
+ mnt->um_dev = strdup(dev);
+ if (mnt->um_dev == NULL)
+ goto done;
+
+ if (asprintf(&fs, "%s%s", dev, path) < 0)
+ goto done;
+
+ mnt->um_fd = open(fs, O_RDONLY);
+ free(fs);
+ if (mnt->um_fd == -1)
+ goto done;
+
+ STAILQ_INSERT_TAIL(&mnt_list, mnt, um_link);
+done:
+ if (errno != 0) {
+ free(mnt->um_dev);
+ if (fd >= 0)
+ close(fd);
+ free(mnt);
+ } else {
+ *data = mnt;
+ }
+
+ return (errno);
+}
+
+static int
+ufs_unmount(const char *dev, void *data)
+{
+ ufs_mnt_t *mnt = data;
+
+ STAILQ_REMOVE(&mnt_list, mnt, ufs_mnt, um_link);
+ free(mnt->um_dev);
+ close(mnt->um_fd);
+ free(mnt);
+ return (0);
+}
Index: stand/mips/beri/loader/devicename.c
===================================================================
--- stand/mips/beri/loader/devicename.c
+++ stand/mips/beri/loader/devicename.c
@@ -195,12 +195,23 @@
int
beri_arch_setcurrdev(struct env_var *ev, int flags, const void *value)
{
- struct disk_devdesc *ncurr;
- int rv;
-
- if ((rv = beri_arch_parsedev(&ncurr, value, NULL)) != 0)
- return(rv);
- free(ncurr);
- env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
- return(0);
+ struct disk_devdesc *ncurr;
+ int rv;
+
+ if ((rv = beri_arch_parsedev(&ncurr, value, NULL)) != 0)
+ return (rv);
+ free(ncurr);
+
+ /* mount new rootfs */
+ rv = mount(value, "/", 0, NULL);
+ if (rv == 0) {
+ /*
+ * Note we unmount only after successful mount because
+ * we do not want to end up without rootfs.
+ */
+ if (ev->ev_value != NULL)
+ unmount(ev->ev_value, 0);
+ env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
+ }
+ return (rv);
}
Index: stand/powerpc/kboot/main.c
===================================================================
--- stand/powerpc/kboot/main.c
+++ stand/powerpc/kboot/main.c
@@ -45,7 +45,6 @@
ssize_t kboot_readin(readin_handle_t fd, vm_offset_t dest, const size_t len);
int kboot_autoload(void);
uint64_t kboot_loadaddr(u_int type, void *data, uint64_t addr);
-int kboot_setcurrdev(struct env_var *ev, int flags, const void *value);
static void kboot_kseg_get(int *nseg, void **ptr);
extern int command_fdt_internal(int argc, char *argv[]);
Index: stand/uboot/lib/devicename.c
===================================================================
--- stand/uboot/lib/devicename.c
+++ stand/uboot/lib/devicename.c
@@ -195,6 +195,17 @@
if ((rv = uboot_parsedev(&ncurr, value, NULL)) != 0)
return (rv);
free(ncurr);
- env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
- return (0);
+
+ /* mount new rootfs */
+ rv = mount(value, "/", 0, NULL);
+ if (rv == 0) {
+ /*
+ * Note we unmount only after successful mount because
+ * we do not want to end up without rootfs.
+ */
+ if (ev->ev_value != NULL)
+ unmount(ev->ev_value, 0);
+ env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
+ }
+ return (rv);
}
Index: stand/userboot/userboot/devicename.c
===================================================================
--- stand/userboot/userboot/devicename.c
+++ stand/userboot/userboot/devicename.c
@@ -222,6 +222,17 @@
if ((rv = userboot_parsedev(&ncurr, value, NULL)) != 0)
return (rv);
free(ncurr);
- env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
- return (0);
+
+ /* mount new rootfs */
+ rv = mount(value, "/", 0, NULL);
+ if (rv == 0) {
+ /*
+ * Note we unmount only after successful mount because
+ * we do not want to end up without rootfs.
+ */
+ if (ev->ev_value != NULL)
+ unmount(ev->ev_value, 0);
+ env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
+ }
+ return (rv);
}

File Metadata

Mime Type
text/plain
Expires
Wed, Apr 30, 11:12 AM (4 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17856770
Default Alt Text
D30848.id93659.diff (16 KB)

Event Timeline