Page MenuHomeFreeBSD

D30848.diff
No OneTemporary

D30848.diff

diff --git a/stand/common/bootstrap.h b/stand/common/bootstrap.h
--- a/stand/common/bootstrap.h
+++ b/stand/common/bootstrap.h
@@ -29,6 +29,7 @@
#ifndef _BOOTSTRAP_H_
#define _BOOTSTRAP_H_
+#include <stand.h>
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/linker_set.h>
@@ -400,6 +401,9 @@
const char *);
int nvstore_unset_var(void *, const char *);
+/* common code to set currdev variable. */
+extern int mount_currdev(struct env_var *, int, const void *);
+
#ifndef CTASSERT
#define CTASSERT(x) _Static_assert(x, "compile-time assertion failed")
#endif
diff --git a/stand/common/misc.c b/stand/common/misc.c
--- a/stand/common/misc.c
+++ b/stand/common/misc.c
@@ -179,3 +179,25 @@
if (devsw[i]->dv_cleanup != NULL)
(devsw[i]->dv_cleanup)();
}
+
+/*
+ * mount new rootfs and unmount old, set "currdev" environment variable.
+ */
+int mount_currdev(struct env_var *ev, int flags, const void *value)
+{
+ int rv;
+
+ /* mount new rootfs */
+ rv = mount(value, "/", 0, NULL);
+ if (rv == 0) {
+ /*
+ * Note we unmount any previously mounted fs only after
+ * successfully mounting the new because we do not want to
+ * end up with unmounted rootfs.
+ */
+ if (ev->ev_value != NULL)
+ unmount(ev->ev_value, 0);
+ env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
+ }
+ return (rv);
+}
diff --git a/stand/efi/boot1/zfs_module.c b/stand/efi/boot1/zfs_module.c
--- a/stand/efi/boot1/zfs_module.c
+++ b/stand/efi/boot1/zfs_module.c
@@ -160,7 +160,7 @@
return (EFI_NOT_FOUND);
}
- if ((err = zfs_mount(spa, 0, &zmount)) != 0) {
+ if ((err = zfs_mount_impl(spa, 0, &zmount)) != 0) {
DPRINTF("Failed to mount pool '%s' (%d)\n", spa->spa_name, err);
return (EFI_NOT_FOUND);
}
diff --git a/stand/efi/libefi/devicename.c b/stand/efi/libefi/devicename.c
--- a/stand/efi/libefi/devicename.c
+++ b/stand/efi/libefi/devicename.c
@@ -209,8 +209,7 @@
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);
+
+ return (mount_currdev(ev, flags, value));
}
diff --git a/stand/efi/loader/main.c b/stand/efi/loader/main.c
--- a/stand/efi/loader/main.c
+++ b/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);
}
@@ -958,6 +955,9 @@
#endif
cons_probe();
+ /* Set up currdev variable to have hooks in place. */
+ env_setenv("currdev", EV_VOLATILE, "", efi_setcurrdev, env_nounset);
+
/* Init the time source */
efi_time_init();
diff --git a/stand/i386/gptzfsboot/Makefile b/stand/i386/gptzfsboot/Makefile
--- a/stand/i386/gptzfsboot/Makefile
+++ b/stand/i386/gptzfsboot/Makefile
@@ -66,7 +66,7 @@
gptldr.out: gptldr.o
${LD} ${LD_FLAGS} -e start --defsym ORG=${ORG1} -T ${LDSCRIPT} -o ${.TARGET} gptldr.o
-OBJS= zfsboot.o sio.o cons.o bcache.o devopen.o disk.o part.o zfs_cmd.o
+OBJS= zfsboot.o sio.o cons.o bcache.o devopen.o disk.o part.o zfs_cmd.o misc.o
CLEANFILES+= gptzfsboot.bin gptzfsboot.out ${OBJS} ${OPENCRYPTO_XTS}
# i386 standalone support library
diff --git a/stand/i386/libi386/devicename.c b/stand/i386/libi386/devicename.c
--- a/stand/i386/libi386/devicename.c
+++ b/stand/i386/libi386/devicename.c
@@ -204,12 +204,12 @@
int
i386_setcurrdev(struct env_var *ev, int flags, const void *value)
{
- struct i386_devdesc *ncurr;
- int rv;
+ 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);
+ if ((rv = i386_parsedev(&ncurr, value, NULL)) != 0)
+ return (rv);
+ free(ncurr);
+
+ return (mount_currdev(ev, flags, value));
}
diff --git a/stand/i386/loader/main.c b/stand/i386/loader/main.c
--- a/stand/i386/loader/main.c
+++ b/stand/i386/loader/main.c
@@ -164,6 +164,10 @@
}
cons_probe();
+ /* Set up currdev variable to have hooks in place. */
+ env_setenv("currdev", EV_VOLATILE | EV_NOHOOK, "",
+ i386_setcurrdev, env_nounset);
+
/*
* Initialise the block cache. Set the upper limit.
*/
diff --git a/stand/i386/zfsboot/Makefile b/stand/i386/zfsboot/Makefile
--- a/stand/i386/zfsboot/Makefile
+++ b/stand/i386/zfsboot/Makefile
@@ -59,7 +59,7 @@
zfsldr.out: zfsldr.o
${LD} ${LD_FLAGS} -e start --defsym ORG=${ORG1} -T ${LDSCRIPT} -o ${.TARGET} zfsldr.o
-OBJS= zfsboot.o sio.o cons.o bcache.o devopen.o disk.o part.o zfs_cmd.o
+OBJS= zfsboot.o sio.o cons.o bcache.o devopen.o disk.o part.o zfs_cmd.o misc.o
CLEANFILES+= zfsboot2 zfsboot.ld zfsboot.ldr zfsboot.bin zfsboot.out \
${OBJS}
diff --git a/stand/i386/zfsboot/zfsboot.c b/stand/i386/zfsboot/zfsboot.c
--- a/stand/i386/zfsboot/zfsboot.c
+++ b/stand/i386/zfsboot/zfsboot.c
@@ -207,6 +207,10 @@
snprintf(boot_devname, sizeof (boot_devname), "disk%d:",
bd_bios2unit(bootinfo.bi_bios_dev));
+ /* Set up currdev variable to have hooks in place. */
+ env_setenv("currdev", EV_VOLATILE, "", i386_setcurrdev,
+ env_nounset);
+
for (i = 0; devsw[i] != NULL; i++)
if (devsw[i]->dv_init != NULL)
(devsw[i]->dv_init)();
diff --git a/stand/libofw/devicename.c b/stand/libofw/devicename.c
--- a/stand/libofw/devicename.c
+++ b/stand/libofw/devicename.c
@@ -134,13 +134,13 @@
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);
+
+ return (mount_currdev(ev, flags, value));
}
diff --git a/stand/libsa/Makefile b/stand/libsa/Makefile
--- a/stand/libsa/Makefile
+++ b/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
diff --git a/stand/libsa/cd9660.c b/stand/libsa/cd9660.c
--- a/stand/libsa/cd9660.c
+++ b/stand/libsa/cd9660.c
@@ -70,6 +70,8 @@
static off_t cd9660_seek(struct open_file *f, off_t offset, int where);
static int cd9660_stat(struct open_file *f, struct stat *sb);
static int cd9660_readdir(struct open_file *f, struct dirent *d);
+static int cd9660_mount(const char *, const char *, void **);
+static int cd9660_unmount(const char *, void *);
static int dirmatch(struct open_file *f, const char *path,
struct iso_directory_record *dp, int use_rrip, int lenskip);
static int rrip_check(struct open_file *f, struct iso_directory_record *dp,
@@ -81,16 +83,28 @@
int lenskip);
struct fs_ops cd9660_fsops = {
- "cd9660",
- cd9660_open,
- cd9660_close,
- cd9660_read,
- null_write,
- cd9660_seek,
- cd9660_stat,
- cd9660_readdir
+ .fs_name = "cd9660",
+ .fo_open = cd9660_open,
+ .fo_close = cd9660_close,
+ .fo_read = cd9660_read,
+ .fo_write = null_write,
+ .fo_seek = cd9660_seek,
+ .fo_stat = cd9660_stat,
+ .fo_readdir = cd9660_readdir,
+ .fo_mount = cd9660_mount,
+ .fo_unmount = cd9660_unmount
};
+typedef struct cd9660_mnt {
+ struct devdesc *cd_dev;
+ int cd_fd;
+ struct iso_directory_record cd_rec;
+ STAILQ_ENTRY(cd9660_mnt) cd_link;
+} cd9660_mnt_t;
+
+typedef STAILQ_HEAD(cd9660_mnt_list, cd9660_mnt) cd9660_mnt_list_t;
+static cd9660_mnt_list_t mnt_list = STAILQ_HEAD_INITIALIZER(mnt_list);
+
#define F_ISDIR 0x0001 /* Directory */
#define F_ROOTDIR 0x0002 /* Root directory */
#define F_RR 0x0004 /* Rock Ridge on this volume */
@@ -281,26 +295,23 @@
}
static int
-cd9660_open(const char *path, struct open_file *f)
+cd9660_read_dr(struct open_file *f, struct iso_directory_record *rec)
{
- struct file *fp = NULL;
- void *buf;
struct iso_primary_descriptor *vd;
- size_t read, dsize, off;
- daddr_t bno, boff;
- struct iso_directory_record rec;
- struct iso_directory_record *dp = NULL;
- int rc, first, use_rrip, lenskip;
- bool isdir = false;
+ size_t read;
+ daddr_t bno;
+ int rc;
- /* First find the volume descriptor */
- buf = malloc(MAX(ISO_DEFAULT_BLOCK_SIZE,
+ errno = 0;
+ vd = malloc(MAX(ISO_DEFAULT_BLOCK_SIZE,
sizeof(struct iso_primary_descriptor)));
- vd = buf;
+ if (vd == NULL)
+ return (errno);
+
for (bno = 16;; bno++) {
twiddle(1);
rc = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(bno),
- ISO_DEFAULT_BLOCK_SIZE, buf, &read);
+ ISO_DEFAULT_BLOCK_SIZE, (char *)vd, &read);
if (rc)
goto out;
if (read != ISO_DEFAULT_BLOCK_SIZE) {
@@ -308,18 +319,61 @@
goto out;
}
rc = EINVAL;
- if (bcmp(vd->id, ISO_STANDARD_ID, sizeof vd->id) != 0)
+ if (bcmp(vd->id, ISO_STANDARD_ID, sizeof(vd->id)) != 0)
goto out;
if (isonum_711(vd->type) == ISO_VD_END)
goto out;
if (isonum_711(vd->type) == ISO_VD_PRIMARY)
break;
}
- if (isonum_723(vd->logical_block_size) != ISO_DEFAULT_BLOCK_SIZE)
+ if (isonum_723(vd->logical_block_size) == ISO_DEFAULT_BLOCK_SIZE) {
+ bcopy(vd->root_directory_record, rec, sizeof(*rec));
+ rc = 0;
+ }
+out:
+ free(vd);
+ return (rc);
+}
+
+static int
+cd9660_open(const char *path, struct open_file *f)
+{
+ struct file *fp = NULL;
+ void *buf;
+ size_t read, dsize, off;
+ daddr_t bno, boff;
+ struct iso_directory_record rec;
+ struct iso_directory_record *dp = NULL;
+ int rc, first, use_rrip, lenskip;
+ bool isdir = false;
+ struct devdesc *dev;
+ cd9660_mnt_t *mnt;
+
+ /* First find the volume descriptor */
+ errno = 0;
+ buf = malloc(MAX(ISO_DEFAULT_BLOCK_SIZE,
+ sizeof(struct iso_primary_descriptor)));
+ if (buf == NULL)
+ return (errno);
+
+ dev = f->f_devdata;
+ STAILQ_FOREACH(mnt, &mnt_list, cd_link) {
+ if (dev->d_dev->dv_type == mnt->cd_dev->d_dev->dv_type &&
+ dev->d_unit == mnt->cd_dev->d_unit)
+ break;
+ }
+
+ rc = 0;
+ if (mnt == NULL)
+ rc = cd9660_read_dr(f, &rec);
+ else
+ rec = mnt->cd_rec;
+
+ if (rc != 0)
goto out;
- bcopy(vd->root_directory_record, &rec, sizeof(rec));
- if (*path == '/') path++; /* eat leading '/' */
+ if (*path == '/')
+ path++; /* eat leading '/' */
first = 1;
use_rrip = 0;
@@ -621,3 +675,57 @@
sb->st_size = fp->f_size;
return 0;
}
+
+static int
+cd9660_mount(const char *dev, const char *path, void **data)
+{
+ cd9660_mnt_t *mnt;
+ struct open_file *f;
+ char *fs;
+
+ errno = 0;
+ mnt = calloc(1, sizeof(*mnt));
+ if (mnt == NULL)
+ return (errno);
+ mnt->cd_fd = -1;
+
+ if (asprintf(&fs, "%s%s", dev, path) < 0)
+ goto done;
+
+ mnt->cd_fd = open(fs, O_RDONLY);
+ free(fs);
+ if (mnt->cd_fd == -1)
+ goto done;
+
+ f = fd2open_file(mnt->cd_fd);
+ /* Is it cd9660 file system? */
+ if (strcmp(f->f_ops->fs_name, "cd9660") == 0) {
+ mnt->cd_dev = f->f_devdata;
+ errno = cd9660_read_dr(f, &mnt->cd_rec);
+ STAILQ_INSERT_TAIL(&mnt_list, mnt, cd_link);
+ } else {
+ errno = ENXIO;
+ }
+
+done:
+ if (errno != 0) {
+ free(mnt->cd_dev);
+ if (mnt->cd_fd >= 0)
+ close(mnt->cd_fd);
+ free(mnt);
+ } else {
+ *data = mnt;
+ }
+ return (errno);
+}
+
+static int
+cd9660_unmount(const char *dev __unused, void *data)
+{
+ cd9660_mnt_t *mnt = data;
+
+ STAILQ_REMOVE(&mnt_list, mnt, cd9660_mnt, cd_link);
+ close(mnt->cd_fd);
+ free(mnt);
+ return (0);
+}
diff --git a/stand/libsa/dosfs.c b/stand/libsa/dosfs.c
--- a/stand/libsa/dosfs.c
+++ b/stand/libsa/dosfs.c
@@ -38,9 +38,19 @@
#include <stddef.h>
#include "stand.h"
+#include "disk.h"
#include "dosfs.h"
+typedef struct dos_mnt {
+ char *dos_dev;
+ DOS_FS *dos_fs;
+ int dos_fd;
+ STAILQ_ENTRY(dos_mnt) dos_link;
+} dos_mnt_t;
+
+typedef STAILQ_HEAD(dos_mnt_list, dos_mnt) dos_mnt_list_t;
+static dos_mnt_list_t mnt_list = STAILQ_HEAD_INITIALIZER(mnt_list);
static int dos_open(const char *path, struct open_file *fd);
static int dos_close(struct open_file *fd);
@@ -48,16 +58,20 @@
static off_t dos_seek(struct open_file *fd, off_t offset, int whence);
static int dos_stat(struct open_file *fd, struct stat *sb);
static int dos_readdir(struct open_file *fd, struct dirent *d);
+static int dos_mount(const char *dev, const char *path, void **data);
+static int dos_unmount(const char *dev, void *data);
struct fs_ops dosfs_fsops = {
- "dosfs",
- dos_open,
- dos_close,
- dos_read,
- null_write,
- dos_seek,
- dos_stat,
- dos_readdir
+ .fs_name = "dosfs",
+ .fo_open = dos_open,
+ .fo_close = dos_close,
+ .fo_read = dos_read,
+ .fo_write = null_write,
+ .fo_seek = dos_seek,
+ .fo_stat = dos_stat,
+ .fo_readdir = dos_readdir,
+ .fo_mount = dos_mount,
+ .fo_unmount = dos_unmount
};
#define SECSIZ 512 /* sector size */
@@ -179,12 +193,11 @@
* Mount DOS filesystem
*/
static int
-dos_mount(DOS_FS *fs, struct open_file *fd)
+dos_mount_impl(DOS_FS *fs, struct open_file *fd)
{
int err;
u_char *buf;
- bzero(fs, sizeof(DOS_FS));
fs->fd = fd;
if ((buf = malloc(secbyt(1))) == NULL)
@@ -215,11 +228,70 @@
return (0);
}
+static int
+dos_mount(const char *dev, const char *path, void **data)
+{
+ char *fs;
+ dos_mnt_t *mnt;
+ struct open_file *f;
+ DOS_FILE *df;
+
+ errno = 0;
+ mnt = calloc(1, sizeof(*mnt));
+ if (mnt == NULL)
+ return (errno);
+ mnt->dos_fd = -1;
+ mnt->dos_dev = strdup(dev);
+ if (mnt->dos_dev == NULL)
+ goto done;
+
+ if (asprintf(&fs, "%s%s", dev, path) < 0)
+ goto done;
+
+ mnt->dos_fd = open(fs, O_RDONLY);
+ free(fs);
+ if (mnt->dos_fd == -1)
+ goto done;
+
+ f = fd2open_file(mnt->dos_fd);
+ if (strcmp(f->f_ops->fs_name, "dosfs") == 0) {
+ df = f->f_fsdata;
+ mnt->dos_fs = df->fs;
+ STAILQ_INSERT_TAIL(&mnt_list, mnt, dos_link);
+ } else {
+ errno = ENXIO;
+ }
+
+done:
+ if (errno != 0) {
+ free(mnt->dos_dev);
+ if (mnt->dos_fd >= 0)
+ close(mnt->dos_fd);
+ free(mnt);
+ } else {
+ *data = mnt;
+ }
+
+ return (errno);
+}
+
+static int
+dos_unmount(const char *dev __unused, void *data)
+{
+ dos_mnt_t *mnt = data;
+
+ STAILQ_REMOVE(&mnt_list, mnt, dos_mnt, dos_link);
+ free(mnt->dos_dev);
+ close(mnt->dos_fd);
+ free(mnt);
+ return (0);
+}
+
/*
* Unmount mounted filesystem
*/
static int
-dos_unmount(DOS_FS *fs)
+dos_unmount_impl(DOS_FS *fs)
{
if (fs->links)
return (EBUSY);
@@ -237,19 +309,32 @@
DOS_DE *de;
DOS_FILE *f;
DOS_FS *fs;
+ dos_mnt_t *mnt;
+ const char *dev;
u_int size, clus;
int err;
- /* Allocate mount structure, associate with open */
- if ((fs = malloc(sizeof(DOS_FS))) == NULL)
- return (errno);
- if ((err = dos_mount(fs, fd))) {
- free(fs);
- return (err);
+ dev = disk_fmtdev(fd->f_devdata);
+ STAILQ_FOREACH(mnt, &mnt_list, dos_link) {
+ if (strcmp(dev, mnt->dos_dev) == 0)
+ break;
+ }
+
+ if (mnt == NULL) {
+ /* Allocate mount structure, associate with open */
+ if ((fs = malloc(sizeof(DOS_FS))) == NULL)
+ return (errno);
+ if ((err = dos_mount_impl(fs, fd))) {
+ free(fs);
+ return (err);
+ }
+ } else {
+ fs = mnt->dos_fs;
}
if ((err = namede(fs, path, &de))) {
- dos_unmount(fs);
+ if (mnt == NULL)
+ dos_unmount_impl(fs);
return (err);
}
@@ -259,19 +344,20 @@
if ((!(de->attr & FA_DIR) && (!clus != !size)) ||
((de->attr & FA_DIR) && size) ||
(clus && !okclus(fs, clus))) {
- dos_unmount(fs);
+ if (mnt == NULL)
+ dos_unmount_impl(fs);
return (EINVAL);
}
- if ((f = malloc(sizeof(DOS_FILE))) == NULL) {
+ if ((f = calloc(1, sizeof(DOS_FILE))) == NULL) {
err = errno;
- dos_unmount(fs);
+ if (mnt == NULL)
+ dos_unmount_impl(fs);
return (err);
}
- bzero(f, sizeof(DOS_FILE));
f->fs = fs;
fs->links++;
f->de = *de;
- fd->f_fsdata = (void *)f;
+ fd->f_fsdata = f;
return (0);
}
@@ -381,7 +467,7 @@
f->fs->links--;
free(f);
- dos_unmount(fs);
+ dos_unmount_impl(fs);
return (0);
}
diff --git a/stand/libsa/mount.c b/stand/libsa/mount.c
new file mode 100644
--- /dev/null
+++ b/stand/libsa/mount.c
@@ -0,0 +1,163 @@
+/*-
+ * 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;
+ unsigned mnt_refcount;
+ 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;
+ mnt->mnt_refcount = 1;
+
+ 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 flags __unused, 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) {
+ mnt->mnt_refcount++;
+ return (0);
+ }
+ }
+
+ for (int i = 0; file_system[i] != NULL; i++) {
+ struct fs_ops *fs;
+
+ fs = file_system[i];
+ if (fs->fo_mount == NULL)
+ continue;
+
+ if (fs->fo_mount(dev, path, &data) != 0)
+ continue;
+
+ rc = add_mnt_info(fs, dev, path, data);
+ if (rc != 0 && mnt->mnt_fs->fo_unmount != NULL) {
+ printf("failed to mount %s: %s\n", dev,
+ strerror(rc));
+ (void)mnt->mnt_fs->fo_unmount(dev, data);
+ }
+ break;
+ }
+
+
+ /*
+ * if rc is -1, it means we have no file system with fo_mount()
+ * callback, or all fo_mount() calls failed. As long as we
+ * have missing fo_mount() callbacks, we allow mount() to return 0.
+ */
+ if (rc == -1)
+ rc = 0;
+
+ return (rc);
+}
+
+int
+unmount(const char *dev, int flags __unused)
+{
+ mnt_info_t *mnt;
+ int rv;
+
+ rv = 0;
+ STAILQ_FOREACH(mnt, &mnt_list, mnt_link) {
+ if (strcmp(dev, mnt->mnt_dev) == 0) {
+ if (mnt->mnt_refcount > 1) {
+ mnt->mnt_refcount--;
+ break;
+ }
+
+ if (mnt->mnt_fs->fo_unmount != NULL)
+ rv = mnt->mnt_fs->fo_unmount(dev,
+ mnt->mnt_data);
+ delete_mnt_info(mnt);
+ break;
+ }
+ }
+
+ if (rv != 0)
+ printf("failed to unmount %s: %d\n", dev, rv);
+ return (0);
+}
diff --git a/stand/libsa/netif.c b/stand/libsa/netif.c
--- a/stand/libsa/netif.c
+++ b/stand/libsa/netif.c
@@ -37,7 +37,6 @@
#include <sys/param.h>
#include <sys/types.h>
#include <sys/cdefs.h>
-#include <sys/mount.h>
#include <string.h>
#include <netinet/in.h>
diff --git a/stand/libsa/stand.h b/stand/libsa/stand.h
--- a/stand/libsa/stand.h
+++ b/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 *);
};
/*
@@ -283,6 +285,8 @@
#define gets(x) ngets((x), 0)
extern int fgetstr(char *buf, int size, int fd);
+extern int mount(const char *dev, const char *path, int flags, void *data);
+extern int unmount(const char *dev, int flags);
extern int open(const char *, int);
#define O_RDONLY 0x0
#define O_WRONLY 0x1
diff --git a/stand/libsa/ufs.c b/stand/libsa/ufs.c
--- a/stand/libsa/ufs.c
+++ b/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 *);
@@ -150,9 +164,7 @@
* Read a new inode into a file structure.
*/
static int
-read_inode(inumber, f)
- ino_t inumber;
- struct open_file *f;
+read_inode(ino_t inumber, struct open_file *f)
{
struct file *fp = (struct file *)f->f_fsdata;
struct fs *fs = fp->f_fs;
@@ -207,10 +219,8 @@
* contains that block.
*/
static int
-block_map(f, file_block, disk_block_p)
- struct open_file *f;
- ufs2_daddr_t file_block;
- ufs2_daddr_t *disk_block_p; /* out */
+block_map(struct open_file *f, ufs2_daddr_t file_block,
+ ufs2_daddr_t *disk_block_p)
{
struct file *fp = (struct file *)f->f_fsdata;
struct fs *fs = fp->f_fs;
@@ -312,10 +322,7 @@
* Write a portion of a file from an internal buffer.
*/
static int
-buf_write_file(f, buf_p, size_p)
- struct open_file *f;
- const char *buf_p;
- size_t *size_p; /* out */
+buf_write_file(struct open_file *f, const char *buf_p, size_t *size_p)
{
struct file *fp = (struct file *)f->f_fsdata;
struct fs *fs = fp->f_fs;
@@ -390,10 +397,7 @@
* the location in the buffer and the amount in the buffer.
*/
static int
-buf_read_file(f, buf_p, size_p)
- struct open_file *f;
- char **buf_p; /* out */
- size_t *size_p; /* out */
+buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
{
struct file *fp = (struct file *)f->f_fsdata;
struct fs *fs = fp->f_fs;
@@ -452,10 +456,7 @@
* i_number.
*/
static int
-search_directory(name, f, inumber_p)
- char *name;
- struct open_file *f;
- ino_t *inumber_p; /* out */
+search_directory(char *name, struct open_file *f, ino_t *inumber_p)
{
struct file *fp = (struct file *)f->f_fsdata;
struct direct *dp;
@@ -502,9 +503,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 +515,41 @@
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));
+ errno = 0;
+ fp = calloc(1, sizeof(struct file));
+ if (fp == NULL)
+ return (errno);
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);
+ /* Is this device mounted? */
+ 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 +693,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);
@@ -711,27 +731,34 @@
}
static int
-ufs_close(f)
- struct open_file *f;
+ufs_close(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);
}
@@ -741,11 +768,7 @@
* Cross block boundaries when necessary.
*/
static int
-ufs_read(f, start, size, resid)
- struct open_file *f;
- void *start;
- size_t size;
- size_t *resid; /* out */
+ufs_read(struct open_file *f, void *start, size_t size, size_t *resid)
{
struct file *fp = (struct file *)f->f_fsdata;
size_t csize;
@@ -783,11 +806,7 @@
* extend the file.
*/
static int
-ufs_write(f, start, size, resid)
- struct open_file *f;
- const void *start;
- size_t size;
- size_t *resid; /* out */
+ufs_write(struct open_file *f, const void *start, size_t size, size_t *resid)
{
struct file *fp = (struct file *)f->f_fsdata;
size_t csize;
@@ -815,10 +834,7 @@
}
static off_t
-ufs_seek(f, offset, where)
- struct open_file *f;
- off_t offset;
- int where;
+ufs_seek(struct open_file *f, off_t offset, int where)
{
struct file *fp = (struct file *)f->f_fsdata;
@@ -840,9 +856,7 @@
}
static int
-ufs_stat(f, sb)
- struct open_file *f;
- struct stat *sb;
+ufs_stat(struct open_file *f, struct stat *sb)
{
struct file *fp = (struct file *)f->f_fsdata;
@@ -894,3 +908,59 @@
strcpy(d->d_name, dp->d_name);
return (0);
}
+
+static int
+ufs_mount(const char *dev, const char *path, void **data)
+{
+ char *fs;
+ ufs_mnt_t *mnt;
+ struct open_file *f;
+
+ errno = 0;
+ 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;
+
+ /* Is it ufs file system? */
+ f = fd2open_file(mnt->um_fd);
+ if (strcmp(f->f_ops->fs_name, "ufs") == 0)
+ STAILQ_INSERT_TAIL(&mnt_list, mnt, um_link);
+ else
+ errno = ENXIO;
+
+done:
+ if (errno != 0) {
+ free(mnt->um_dev);
+ if (mnt->um_fd >= 0)
+ close(mnt->um_fd);
+ free(mnt);
+ } else {
+ *data = mnt;
+ }
+
+ return (errno);
+}
+
+static int
+ufs_unmount(const char *dev __unused, 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);
+}
diff --git a/stand/libsa/zfs/zfs.c b/stand/libsa/zfs/zfs.c
--- a/stand/libsa/zfs/zfs.c
+++ b/stand/libsa/zfs/zfs.c
@@ -58,6 +58,8 @@
static off_t zfs_seek(struct open_file *f, off_t offset, int where);
static int zfs_stat(struct open_file *f, struct stat *sb);
static int zfs_readdir(struct open_file *f, struct dirent *d);
+static int zfs_mount(const char *dev, const char *path, void **data);
+static int zfs_unmount(const char *dev, void *data);
static void zfs_bootenv_initial(const char *envname, spa_t *spa,
const char *name, const char *dsname, int checkpoint);
@@ -67,14 +69,16 @@
struct devsw zfs_dev;
struct fs_ops zfs_fsops = {
- "zfs",
- zfs_open,
- zfs_close,
- zfs_read,
- null_write,
- zfs_seek,
- zfs_stat,
- zfs_readdir
+ .fs_name = "zfs",
+ .fo_open = zfs_open,
+ .fo_close = zfs_close,
+ .fo_read = zfs_read,
+ .fo_write = null_write,
+ .fo_seek = zfs_seek,
+ .fo_stat = zfs_stat,
+ .fo_readdir = zfs_readdir,
+ .fo_mount = zfs_mount,
+ .fo_unmount = zfs_unmount
};
/*
@@ -362,6 +366,74 @@
}
}
+/*
+ * if path is NULL, create mount structure, but do not add it to list.
+ */
+static int
+zfs_mount(const char *dev, const char *path, void **data)
+{
+ struct zfs_devdesc *zfsdev;
+ spa_t *spa;
+ struct zfsmount *mnt;
+ int rv;
+
+ errno = 0;
+ zfsdev = malloc(sizeof(*zfsdev));
+ if (zfsdev == NULL)
+ return (errno);
+
+ rv = zfs_parsedev(zfsdev, dev + 3, NULL);
+ if (rv != 0) {
+ free(zfsdev);
+ return (rv);
+ }
+
+ spa = spa_find_by_dev(zfsdev);
+ if (spa == NULL)
+ return (ENXIO);
+
+ mnt = calloc(1, sizeof(*mnt));
+ if (mnt != NULL && path != NULL)
+ mnt->path = strdup(path);
+ rv = errno;
+
+ if (mnt != NULL)
+ rv = zfs_mount_impl(spa, zfsdev->root_guid, mnt);
+ free(zfsdev);
+
+ if (rv == 0 && mnt != NULL && mnt->objset.os_type != DMU_OST_ZFS) {
+ printf("Unexpected object set type %ju\n",
+ (uintmax_t)mnt->objset.os_type);
+ rv = EIO;
+ }
+
+ if (rv != 0) {
+ if (mnt != NULL)
+ free(mnt->path);
+ free(mnt);
+ return (rv);
+ }
+
+ if (mnt != NULL) {
+ *data = mnt;
+ if (path != NULL)
+ STAILQ_INSERT_TAIL(&zfsmount, mnt, next);
+ }
+
+ return (rv);
+}
+
+static int
+zfs_unmount(const char *dev, void *data)
+{
+ struct zfsmount *mnt = data;
+
+ STAILQ_REMOVE(&zfsmount, mnt, zfsmount, next);
+ free(mnt->path);
+ free(mnt);
+ return (0);
+}
+
static int
vdev_read(vdev_t *vdev, void *priv, off_t offset, void *buf, size_t bytes)
{
@@ -1503,32 +1575,45 @@
if ((spa = spa_find_by_dev(dev)) == NULL)
return (ENXIO);
- mount = malloc(sizeof(*mount));
- if (mount == NULL)
- rv = ENOMEM;
- else
- rv = zfs_mount(spa, dev->root_guid, mount);
- if (rv != 0) {
- free(mount);
- return (rv);
+ STAILQ_FOREACH(mount, &zfsmount, next) {
+ if (spa->spa_guid == mount->spa->spa_guid)
+ break;
}
- if (mount->objset.os_type != DMU_OST_ZFS) {
- printf("Unexpected object set type %ju\n",
- (uintmax_t)mount->objset.os_type);
- free(mount);
- return (EIO);
+
+ rv = 0;
+ /* This device is not set as currdev, mount us private copy. */
+ if (mount == NULL)
+ rv = zfs_mount(zfs_fmtdev(dev), NULL, (void **)&mount);
+
+ if (rv == 0) {
+ f->f_devdata = mount;
+ free(dev);
}
- f->f_devdata = mount;
- free(dev);
- return (0);
+ return (rv);
}
static int
zfs_dev_close(struct open_file *f)
{
+ struct zfsmount *mnt, *mount;
+
+ mnt = f->f_devdata;
+
+ STAILQ_FOREACH(mount, &zfsmount, next) {
+ if (mnt->spa->spa_guid == mount->spa->spa_guid)
+ break;
+ }
+
+ /*
+ * devclose() will free f->f_devdata, but since we do have
+ * pointer to zfsmount structure in f->f_devdata, and
+ * zfs_unmount() will also free the zfsmount structure,
+ * we will get double free. To prevent double free,
+ * we must set f_devdata to NULL there.
+ */
+ if (mount != NULL)
+ f->f_devdata = NULL;
- free(f->f_devdata);
- f->f_devdata = NULL;
return (0);
}
diff --git a/stand/libsa/zfs/zfsimpl.c b/stand/libsa/zfs/zfsimpl.c
--- a/stand/libsa/zfs/zfsimpl.c
+++ b/stand/libsa/zfs/zfsimpl.c
@@ -47,11 +47,15 @@
#endif
struct zfsmount {
- const spa_t *spa;
- objset_phys_t objset;
- uint64_t rootobj;
+ char *path;
+ const spa_t *spa;
+ objset_phys_t objset;
+ uint64_t rootobj;
+ STAILQ_ENTRY(zfsmount) next;
};
-static struct zfsmount zfsmount __unused;
+
+typedef STAILQ_HEAD(zfs_mnt_list, zfsmount) zfs_mnt_list_t;
+static zfs_mnt_list_t zfsmount = STAILQ_HEAD_INITIALIZER(zfsmount);
/*
* The indirect_child_t represents the vdev that we will read from, when we
@@ -3321,7 +3325,7 @@
}
static int
-zfs_mount(const spa_t *spa, uint64_t rootobj, struct zfsmount *mount)
+zfs_mount_impl(const spa_t *spa, uint64_t rootobj, struct zfsmount *mount)
{
mount->spa = spa;
diff --git a/stand/mips/beri/loader/devicename.c b/stand/mips/beri/loader/devicename.c
--- a/stand/mips/beri/loader/devicename.c
+++ b/stand/mips/beri/loader/devicename.c
@@ -195,12 +195,12 @@
int
beri_arch_setcurrdev(struct env_var *ev, int flags, const void *value)
{
- struct disk_devdesc *ncurr;
- int rv;
+ 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);
+ if ((rv = beri_arch_parsedev(&ncurr, value, NULL)) != 0)
+ return (rv);
+ free(ncurr);
+
+ return (mount_currdev(ev, flags, value));
}
diff --git a/stand/powerpc/kboot/main.c b/stand/powerpc/kboot/main.c
--- a/stand/powerpc/kboot/main.c
+++ b/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[]);
diff --git a/stand/powerpc/ofw/main.c b/stand/powerpc/ofw/main.c
--- a/stand/powerpc/ofw/main.c
+++ b/stand/powerpc/ofw/main.c
@@ -137,6 +137,9 @@
*/
cons_probe();
+ /* Set up currdev variable to have hooks in place. */
+ env_setenv("currdev", EV_VOLATILE, "", ofw_setcurrdev, env_nounset);
+
/*
* March through the device switch probing for things.
*/
diff --git a/stand/uboot/common/main.c b/stand/uboot/common/main.c
--- a/stand/uboot/common/main.c
+++ b/stand/uboot/common/main.c
@@ -475,6 +475,9 @@
meminfo();
+ /* Set up currdev variable to have hooks in place. */
+ env_setenv("currdev", EV_VOLATILE, "", uboot_setcurrdev, env_nounset);
+
/*
* Enumerate U-Boot devices
*/
diff --git a/stand/uboot/lib/devicename.c b/stand/uboot/lib/devicename.c
--- a/stand/uboot/lib/devicename.c
+++ b/stand/uboot/lib/devicename.c
@@ -195,6 +195,6 @@
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);
+
+ return (mount_currdev(ev, flags, value));
}
diff --git a/stand/userboot/userboot/devicename.c b/stand/userboot/userboot/devicename.c
--- a/stand/userboot/userboot/devicename.c
+++ b/stand/userboot/userboot/devicename.c
@@ -222,6 +222,6 @@
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);
+
+ return (mount_currdev(ev, flags, value));
}
diff --git a/stand/userboot/userboot/main.c b/stand/userboot/userboot/main.c
--- a/stand/userboot/userboot/main.c
+++ b/stand/userboot/userboot/main.c
@@ -159,6 +159,10 @@
*/
cons_probe();
+ /* Set up currdev variable to have hooks in place. */
+ env_setenv("currdev", EV_VOLATILE, "",
+ userboot_setcurrdev, env_nounset);
+
printf("\n%s", bootprog_info);
#if 0
printf("Memory: %ld k\n", memsize() / 1024);

File Metadata

Mime Type
text/plain
Expires
Fri, Jan 24, 10:53 PM (45 m, 15 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16108007
Default Alt Text
D30848.diff (36 KB)

Event Timeline