Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F115844120
D30848.id93659.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D30848.id93659.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D30848: loader: implement mount/unmount rootfs
Attached
Detach File
Event Timeline
Log In to Comment