loader: implement mount/unmount rootfs
We want to keep our root file system open to preserve bcache segment between file accesses, thus reducing physical disk IO. Reviewed by: imp, allanjude, kevans (previous version) Differential Revision: https://reviews.freebsd.org/D30848 MFC after: 1 month
This commit is contained in:
parent
c90cab0d66
commit
b4cb3fe0e3
@ -29,6 +29,7 @@
|
|||||||
#ifndef _BOOTSTRAP_H_
|
#ifndef _BOOTSTRAP_H_
|
||||||
#define _BOOTSTRAP_H_
|
#define _BOOTSTRAP_H_
|
||||||
|
|
||||||
|
#include <stand.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <sys/linker_set.h>
|
#include <sys/linker_set.h>
|
||||||
@ -400,6 +401,9 @@ int nvstore_set_var_from_string(void *, const char *, const char *,
|
|||||||
const char *);
|
const char *);
|
||||||
int nvstore_unset_var(void *, 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
|
#ifndef CTASSERT
|
||||||
#define CTASSERT(x) _Static_assert(x, "compile-time assertion failed")
|
#define CTASSERT(x) _Static_assert(x, "compile-time assertion failed")
|
||||||
#endif
|
#endif
|
||||||
|
@ -179,3 +179,25 @@ dev_cleanup(void)
|
|||||||
if (devsw[i]->dv_cleanup != NULL)
|
if (devsw[i]->dv_cleanup != NULL)
|
||||||
(devsw[i]->dv_cleanup)();
|
(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);
|
||||||
|
}
|
||||||
|
@ -160,7 +160,7 @@ load(const char *filepath, dev_info_t *devinfo, void **bufp, size_t *bufsize)
|
|||||||
return (EFI_NOT_FOUND);
|
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);
|
DPRINTF("Failed to mount pool '%s' (%d)\n", spa->spa_name, err);
|
||||||
return (EFI_NOT_FOUND);
|
return (EFI_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
@ -209,8 +209,7 @@ efi_setcurrdev(struct env_var *ev, int flags, const void *value)
|
|||||||
rv = efi_parsedev(&ncurr, value, NULL);
|
rv = efi_parsedev(&ncurr, value, NULL);
|
||||||
if (rv != 0)
|
if (rv != 0)
|
||||||
return (rv);
|
return (rv);
|
||||||
|
|
||||||
free(ncurr);
|
free(ncurr);
|
||||||
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
|
|
||||||
return (0);
|
return (mount_currdev(ev, flags, value));
|
||||||
}
|
}
|
||||||
|
@ -187,15 +187,12 @@ static void
|
|||||||
set_currdev(const char *devname)
|
set_currdev(const char *devname)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
env_setenv("currdev", EV_VOLATILE | EV_NOHOOK, devname, efi_setcurrdev,
|
|
||||||
env_nounset);
|
env_nounset);
|
||||||
|
/*
|
||||||
|
* Don't execute hook here; the loaddev hook makes it immutable
|
||||||
|
* once we've determined what the proper currdev is.
|
||||||
|
*/
|
||||||
env_setenv("loaddev", EV_VOLATILE | EV_NOHOOK, devname, env_noset,
|
env_setenv("loaddev", EV_VOLATILE | EV_NOHOOK, devname, env_noset,
|
||||||
env_nounset);
|
env_nounset);
|
||||||
}
|
}
|
||||||
@ -958,6 +955,9 @@ main(int argc, CHAR16 *argv[])
|
|||||||
#endif
|
#endif
|
||||||
cons_probe();
|
cons_probe();
|
||||||
|
|
||||||
|
/* Set up currdev variable to have hooks in place. */
|
||||||
|
env_setenv("currdev", EV_VOLATILE, "", efi_setcurrdev, env_nounset);
|
||||||
|
|
||||||
/* Init the time source */
|
/* Init the time source */
|
||||||
efi_time_init();
|
efi_time_init();
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ gptldr.bin: gptldr.out
|
|||||||
gptldr.out: gptldr.o
|
gptldr.out: gptldr.o
|
||||||
${LD} ${LD_FLAGS} -e start --defsym ORG=${ORG1} -T ${LDSCRIPT} -o ${.TARGET} 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}
|
CLEANFILES+= gptzfsboot.bin gptzfsboot.out ${OBJS} ${OPENCRYPTO_XTS}
|
||||||
|
|
||||||
# i386 standalone support library
|
# i386 standalone support library
|
||||||
|
@ -204,12 +204,12 @@ i386_fmtdev(void *vdev)
|
|||||||
int
|
int
|
||||||
i386_setcurrdev(struct env_var *ev, int flags, const void *value)
|
i386_setcurrdev(struct env_var *ev, int flags, const void *value)
|
||||||
{
|
{
|
||||||
struct i386_devdesc *ncurr;
|
struct i386_devdesc *ncurr;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
if ((rv = i386_parsedev(&ncurr, value, NULL)) != 0)
|
if ((rv = i386_parsedev(&ncurr, value, NULL)) != 0)
|
||||||
return(rv);
|
return (rv);
|
||||||
free(ncurr);
|
free(ncurr);
|
||||||
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
|
|
||||||
return(0);
|
return (mount_currdev(ev, flags, value));
|
||||||
}
|
}
|
||||||
|
@ -164,6 +164,10 @@ main(void)
|
|||||||
}
|
}
|
||||||
cons_probe();
|
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.
|
* Initialise the block cache. Set the upper limit.
|
||||||
*/
|
*/
|
||||||
|
@ -59,7 +59,7 @@ zfsboot1: zfsldr.out
|
|||||||
zfsldr.out: zfsldr.o
|
zfsldr.out: zfsldr.o
|
||||||
${LD} ${LD_FLAGS} -e start --defsym ORG=${ORG1} -T ${LDSCRIPT} -o ${.TARGET} 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 \
|
CLEANFILES+= zfsboot2 zfsboot.ld zfsboot.ldr zfsboot.bin zfsboot.out \
|
||||||
${OBJS}
|
${OBJS}
|
||||||
|
|
||||||
|
@ -207,6 +207,10 @@ main(void)
|
|||||||
snprintf(boot_devname, sizeof (boot_devname), "disk%d:",
|
snprintf(boot_devname, sizeof (boot_devname), "disk%d:",
|
||||||
bd_bios2unit(bootinfo.bi_bios_dev));
|
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++)
|
for (i = 0; devsw[i] != NULL; i++)
|
||||||
if (devsw[i]->dv_init != NULL)
|
if (devsw[i]->dv_init != NULL)
|
||||||
(devsw[i]->dv_init)();
|
(devsw[i]->dv_init)();
|
||||||
|
@ -134,13 +134,13 @@ ofw_parsedev(struct ofw_devdesc **dev, const char *devspec, const char **path)
|
|||||||
int
|
int
|
||||||
ofw_setcurrdev(struct env_var *ev, int flags, const void *value)
|
ofw_setcurrdev(struct env_var *ev, int flags, const void *value)
|
||||||
{
|
{
|
||||||
struct ofw_devdesc *ncurr;
|
struct ofw_devdesc *ncurr;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
if ((rv = ofw_parsedev(&ncurr, value, NULL)) != 0)
|
if ((rv = ofw_parsedev(&ncurr, value, NULL)) != 0)
|
||||||
return rv;
|
return (rv);
|
||||||
|
|
||||||
free(ncurr);
|
free(ncurr);
|
||||||
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
|
|
||||||
return 0;
|
return (mount_currdev(ev, flags, value));
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ CLEANDIRS+=${FAKE_DIRS}
|
|||||||
CLEANFILES+= ${SAFE_INCS} ${STAND_H_INC} ${OTHER_INC}
|
CLEANFILES+= ${SAFE_INCS} ${STAND_H_INC} ${OTHER_INC}
|
||||||
|
|
||||||
# io routines
|
# 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
|
fstat.c close.c lseek.c open.c read.c write.c readdir.c
|
||||||
|
|
||||||
# SMBios routines
|
# SMBios routines
|
||||||
|
@ -70,6 +70,8 @@ static int cd9660_read(struct open_file *f, void *buf, size_t size,
|
|||||||
static off_t cd9660_seek(struct open_file *f, off_t offset, int where);
|
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_stat(struct open_file *f, struct stat *sb);
|
||||||
static int cd9660_readdir(struct open_file *f, struct dirent *d);
|
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,
|
static int dirmatch(struct open_file *f, const char *path,
|
||||||
struct iso_directory_record *dp, int use_rrip, int lenskip);
|
struct iso_directory_record *dp, int use_rrip, int lenskip);
|
||||||
static int rrip_check(struct open_file *f, struct iso_directory_record *dp,
|
static int rrip_check(struct open_file *f, struct iso_directory_record *dp,
|
||||||
@ -81,16 +83,28 @@ static ISO_SUSP_HEADER *susp_lookup_record(struct open_file *f,
|
|||||||
int lenskip);
|
int lenskip);
|
||||||
|
|
||||||
struct fs_ops cd9660_fsops = {
|
struct fs_ops cd9660_fsops = {
|
||||||
"cd9660",
|
.fs_name = "cd9660",
|
||||||
cd9660_open,
|
.fo_open = cd9660_open,
|
||||||
cd9660_close,
|
.fo_close = cd9660_close,
|
||||||
cd9660_read,
|
.fo_read = cd9660_read,
|
||||||
null_write,
|
.fo_write = null_write,
|
||||||
cd9660_seek,
|
.fo_seek = cd9660_seek,
|
||||||
cd9660_stat,
|
.fo_stat = cd9660_stat,
|
||||||
cd9660_readdir
|
.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_ISDIR 0x0001 /* Directory */
|
||||||
#define F_ROOTDIR 0x0002 /* Root directory */
|
#define F_ROOTDIR 0x0002 /* Root directory */
|
||||||
#define F_RR 0x0004 /* Rock Ridge on this volume */
|
#define F_RR 0x0004 /* Rock Ridge on this volume */
|
||||||
@ -281,26 +295,23 @@ dirmatch(struct open_file *f, const char *path, struct iso_directory_record *dp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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;
|
struct iso_primary_descriptor *vd;
|
||||||
size_t read, dsize, off;
|
size_t read;
|
||||||
daddr_t bno, boff;
|
daddr_t bno;
|
||||||
struct iso_directory_record rec;
|
int rc;
|
||||||
struct iso_directory_record *dp = NULL;
|
|
||||||
int rc, first, use_rrip, lenskip;
|
|
||||||
bool isdir = false;
|
|
||||||
|
|
||||||
/* First find the volume descriptor */
|
errno = 0;
|
||||||
buf = malloc(MAX(ISO_DEFAULT_BLOCK_SIZE,
|
vd = malloc(MAX(ISO_DEFAULT_BLOCK_SIZE,
|
||||||
sizeof(struct iso_primary_descriptor)));
|
sizeof(struct iso_primary_descriptor)));
|
||||||
vd = buf;
|
if (vd == NULL)
|
||||||
|
return (errno);
|
||||||
|
|
||||||
for (bno = 16;; bno++) {
|
for (bno = 16;; bno++) {
|
||||||
twiddle(1);
|
twiddle(1);
|
||||||
rc = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(bno),
|
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)
|
if (rc)
|
||||||
goto out;
|
goto out;
|
||||||
if (read != ISO_DEFAULT_BLOCK_SIZE) {
|
if (read != ISO_DEFAULT_BLOCK_SIZE) {
|
||||||
@ -308,18 +319,61 @@ cd9660_open(const char *path, struct open_file *f)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
rc = EINVAL;
|
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;
|
goto out;
|
||||||
if (isonum_711(vd->type) == ISO_VD_END)
|
if (isonum_711(vd->type) == ISO_VD_END)
|
||||||
goto out;
|
goto out;
|
||||||
if (isonum_711(vd->type) == ISO_VD_PRIMARY)
|
if (isonum_711(vd->type) == ISO_VD_PRIMARY)
|
||||||
break;
|
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;
|
goto out;
|
||||||
|
|
||||||
bcopy(vd->root_directory_record, &rec, sizeof(rec));
|
if (*path == '/')
|
||||||
if (*path == '/') path++; /* eat leading '/' */
|
path++; /* eat leading '/' */
|
||||||
|
|
||||||
first = 1;
|
first = 1;
|
||||||
use_rrip = 0;
|
use_rrip = 0;
|
||||||
@ -621,3 +675,57 @@ cd9660_stat(struct open_file *f, struct stat *sb)
|
|||||||
sb->st_size = fp->f_size;
|
sb->st_size = fp->f_size;
|
||||||
return 0;
|
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);
|
||||||
|
}
|
||||||
|
@ -38,9 +38,19 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "stand.h"
|
#include "stand.h"
|
||||||
|
#include "disk.h"
|
||||||
|
|
||||||
#include "dosfs.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_open(const char *path, struct open_file *fd);
|
||||||
static int dos_close(struct open_file *fd);
|
static int dos_close(struct open_file *fd);
|
||||||
@ -48,16 +58,20 @@ static int dos_read(struct open_file *fd, void *buf, size_t size, size_t *resid)
|
|||||||
static off_t dos_seek(struct open_file *fd, off_t offset, int whence);
|
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_stat(struct open_file *fd, struct stat *sb);
|
||||||
static int dos_readdir(struct open_file *fd, struct dirent *d);
|
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 = {
|
struct fs_ops dosfs_fsops = {
|
||||||
"dosfs",
|
.fs_name = "dosfs",
|
||||||
dos_open,
|
.fo_open = dos_open,
|
||||||
dos_close,
|
.fo_close = dos_close,
|
||||||
dos_read,
|
.fo_read = dos_read,
|
||||||
null_write,
|
.fo_write = null_write,
|
||||||
dos_seek,
|
.fo_seek = dos_seek,
|
||||||
dos_stat,
|
.fo_stat = dos_stat,
|
||||||
dos_readdir
|
.fo_readdir = dos_readdir,
|
||||||
|
.fo_mount = dos_mount,
|
||||||
|
.fo_unmount = dos_unmount
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SECSIZ 512 /* sector size */
|
#define SECSIZ 512 /* sector size */
|
||||||
@ -179,12 +193,11 @@ dos_read_fatblk(DOS_FS *fs, struct open_file *fd, u_int blknum)
|
|||||||
* Mount DOS filesystem
|
* Mount DOS filesystem
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
dos_mount(DOS_FS *fs, struct open_file *fd)
|
dos_mount_impl(DOS_FS *fs, struct open_file *fd)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
u_char *buf;
|
u_char *buf;
|
||||||
|
|
||||||
bzero(fs, sizeof(DOS_FS));
|
|
||||||
fs->fd = fd;
|
fs->fd = fd;
|
||||||
|
|
||||||
if ((buf = malloc(secbyt(1))) == NULL)
|
if ((buf = malloc(secbyt(1))) == NULL)
|
||||||
@ -215,11 +228,70 @@ dos_mount(DOS_FS *fs, struct open_file *fd)
|
|||||||
return (0);
|
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
|
* Unmount mounted filesystem
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
dos_unmount(DOS_FS *fs)
|
dos_unmount_impl(DOS_FS *fs)
|
||||||
{
|
{
|
||||||
if (fs->links)
|
if (fs->links)
|
||||||
return (EBUSY);
|
return (EBUSY);
|
||||||
@ -237,19 +309,32 @@ dos_open(const char *path, struct open_file *fd)
|
|||||||
DOS_DE *de;
|
DOS_DE *de;
|
||||||
DOS_FILE *f;
|
DOS_FILE *f;
|
||||||
DOS_FS *fs;
|
DOS_FS *fs;
|
||||||
|
dos_mnt_t *mnt;
|
||||||
|
const char *dev;
|
||||||
u_int size, clus;
|
u_int size, clus;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* Allocate mount structure, associate with open */
|
dev = disk_fmtdev(fd->f_devdata);
|
||||||
if ((fs = malloc(sizeof(DOS_FS))) == NULL)
|
STAILQ_FOREACH(mnt, &mnt_list, dos_link) {
|
||||||
return (errno);
|
if (strcmp(dev, mnt->dos_dev) == 0)
|
||||||
if ((err = dos_mount(fs, fd))) {
|
break;
|
||||||
free(fs);
|
}
|
||||||
return (err);
|
|
||||||
|
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))) {
|
if ((err = namede(fs, path, &de))) {
|
||||||
dos_unmount(fs);
|
if (mnt == NULL)
|
||||||
|
dos_unmount_impl(fs);
|
||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,19 +344,20 @@ dos_open(const char *path, struct open_file *fd)
|
|||||||
if ((!(de->attr & FA_DIR) && (!clus != !size)) ||
|
if ((!(de->attr & FA_DIR) && (!clus != !size)) ||
|
||||||
((de->attr & FA_DIR) && size) ||
|
((de->attr & FA_DIR) && size) ||
|
||||||
(clus && !okclus(fs, clus))) {
|
(clus && !okclus(fs, clus))) {
|
||||||
dos_unmount(fs);
|
if (mnt == NULL)
|
||||||
|
dos_unmount_impl(fs);
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
}
|
}
|
||||||
if ((f = malloc(sizeof(DOS_FILE))) == NULL) {
|
if ((f = calloc(1, sizeof(DOS_FILE))) == NULL) {
|
||||||
err = errno;
|
err = errno;
|
||||||
dos_unmount(fs);
|
if (mnt == NULL)
|
||||||
|
dos_unmount_impl(fs);
|
||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
bzero(f, sizeof(DOS_FILE));
|
|
||||||
f->fs = fs;
|
f->fs = fs;
|
||||||
fs->links++;
|
fs->links++;
|
||||||
f->de = *de;
|
f->de = *de;
|
||||||
fd->f_fsdata = (void *)f;
|
fd->f_fsdata = f;
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,7 +467,7 @@ dos_close(struct open_file *fd)
|
|||||||
|
|
||||||
f->fs->links--;
|
f->fs->links--;
|
||||||
free(f);
|
free(f);
|
||||||
dos_unmount(fs);
|
dos_unmount_impl(fs);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
163
stand/libsa/mount.c
Normal file
163
stand/libsa/mount.c
Normal file
@ -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);
|
||||||
|
}
|
@ -37,7 +37,6 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
#include <sys/mount.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
@ -111,6 +111,8 @@ struct fs_ops {
|
|||||||
off_t (*fo_seek)(struct open_file *f, off_t offset, int where);
|
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_stat)(struct open_file *f, struct stat *sb);
|
||||||
int (*fo_readdir)(struct open_file *f, struct dirent *d);
|
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 @@ extern void ngets(char *, int);
|
|||||||
#define gets(x) ngets((x), 0)
|
#define gets(x) ngets((x), 0)
|
||||||
extern int fgetstr(char *buf, int size, int fd);
|
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);
|
extern int open(const char *, int);
|
||||||
#define O_RDONLY 0x0
|
#define O_RDONLY 0x0
|
||||||
#define O_WRONLY 0x1
|
#define O_WRONLY 0x1
|
||||||
|
@ -81,6 +81,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <ufs/ufs/dir.h>
|
#include <ufs/ufs/dir.h>
|
||||||
#include <ufs/ffs/fs.h>
|
#include <ufs/ffs/fs.h>
|
||||||
#include "stand.h"
|
#include "stand.h"
|
||||||
|
#include "disk.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
static int ufs_open(const char *path, struct open_file *f);
|
static int ufs_open(const char *path, struct open_file *f);
|
||||||
@ -91,16 +92,20 @@ static int ufs_read(struct open_file *f, void *buf, size_t size, size_t *resid);
|
|||||||
static off_t ufs_seek(struct open_file *f, off_t offset, int where);
|
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_stat(struct open_file *f, struct stat *sb);
|
||||||
static int ufs_readdir(struct open_file *f, struct dirent *d);
|
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 = {
|
struct fs_ops ufs_fsops = {
|
||||||
"ufs",
|
.fs_name = "ufs",
|
||||||
ufs_open,
|
.fo_open = ufs_open,
|
||||||
ufs_close,
|
.fo_close = ufs_close,
|
||||||
ufs_read,
|
.fo_read = ufs_read,
|
||||||
ufs_write,
|
.fo_write = ufs_write,
|
||||||
ufs_seek,
|
.fo_seek = ufs_seek,
|
||||||
ufs_stat,
|
.fo_stat = ufs_stat,
|
||||||
ufs_readdir
|
.fo_readdir = ufs_readdir,
|
||||||
|
.fo_mount = ufs_mount,
|
||||||
|
.fo_unmount = ufs_unmount
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -130,6 +135,15 @@ struct file {
|
|||||||
((fp)->f_fs->fs_magic == FS_UFS1_MAGIC ? \
|
((fp)->f_fs->fs_magic == FS_UFS1_MAGIC ? \
|
||||||
(fp)->f_di.di1.field : (fp)->f_di.di2.field)
|
(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 read_inode(ino_t, struct open_file *);
|
||||||
static int block_map(struct open_file *, ufs2_daddr_t, ufs2_daddr_t *);
|
static int block_map(struct open_file *, ufs2_daddr_t, ufs2_daddr_t *);
|
||||||
static int buf_read_file(struct open_file *, char **, size_t *);
|
static int buf_read_file(struct open_file *, char **, size_t *);
|
||||||
@ -150,9 +164,7 @@ int ffs_sbget(void *, struct fs **, off_t, char *,
|
|||||||
* Read a new inode into a file structure.
|
* Read a new inode into a file structure.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
read_inode(inumber, f)
|
read_inode(ino_t inumber, struct open_file *f)
|
||||||
ino_t inumber;
|
|
||||||
struct open_file *f;
|
|
||||||
{
|
{
|
||||||
struct file *fp = (struct file *)f->f_fsdata;
|
struct file *fp = (struct file *)f->f_fsdata;
|
||||||
struct fs *fs = fp->f_fs;
|
struct fs *fs = fp->f_fs;
|
||||||
@ -207,10 +219,8 @@ read_inode(inumber, f)
|
|||||||
* contains that block.
|
* contains that block.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
block_map(f, file_block, disk_block_p)
|
block_map(struct open_file *f, ufs2_daddr_t file_block,
|
||||||
struct open_file *f;
|
ufs2_daddr_t *disk_block_p)
|
||||||
ufs2_daddr_t file_block;
|
|
||||||
ufs2_daddr_t *disk_block_p; /* out */
|
|
||||||
{
|
{
|
||||||
struct file *fp = (struct file *)f->f_fsdata;
|
struct file *fp = (struct file *)f->f_fsdata;
|
||||||
struct fs *fs = fp->f_fs;
|
struct fs *fs = fp->f_fs;
|
||||||
@ -312,10 +322,7 @@ block_map(f, file_block, disk_block_p)
|
|||||||
* Write a portion of a file from an internal buffer.
|
* Write a portion of a file from an internal buffer.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
buf_write_file(f, buf_p, size_p)
|
buf_write_file(struct open_file *f, const char *buf_p, size_t *size_p)
|
||||||
struct open_file *f;
|
|
||||||
const char *buf_p;
|
|
||||||
size_t *size_p; /* out */
|
|
||||||
{
|
{
|
||||||
struct file *fp = (struct file *)f->f_fsdata;
|
struct file *fp = (struct file *)f->f_fsdata;
|
||||||
struct fs *fs = fp->f_fs;
|
struct fs *fs = fp->f_fs;
|
||||||
@ -390,10 +397,7 @@ buf_write_file(f, buf_p, size_p)
|
|||||||
* the location in the buffer and the amount in the buffer.
|
* the location in the buffer and the amount in the buffer.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
buf_read_file(f, buf_p, size_p)
|
buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
|
||||||
struct open_file *f;
|
|
||||||
char **buf_p; /* out */
|
|
||||||
size_t *size_p; /* out */
|
|
||||||
{
|
{
|
||||||
struct file *fp = (struct file *)f->f_fsdata;
|
struct file *fp = (struct file *)f->f_fsdata;
|
||||||
struct fs *fs = fp->f_fs;
|
struct fs *fs = fp->f_fs;
|
||||||
@ -452,10 +456,7 @@ buf_read_file(f, buf_p, size_p)
|
|||||||
* i_number.
|
* i_number.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
search_directory(name, f, inumber_p)
|
search_directory(char *name, struct open_file *f, ino_t *inumber_p)
|
||||||
char *name;
|
|
||||||
struct open_file *f;
|
|
||||||
ino_t *inumber_p; /* out */
|
|
||||||
{
|
{
|
||||||
struct file *fp = (struct file *)f->f_fsdata;
|
struct file *fp = (struct file *)f->f_fsdata;
|
||||||
struct direct *dp;
|
struct direct *dp;
|
||||||
@ -502,9 +503,7 @@ search_directory(name, f, inumber_p)
|
|||||||
* Open a file.
|
* Open a file.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ufs_open(upath, f)
|
ufs_open(const char *upath, struct open_file *f)
|
||||||
const char *upath;
|
|
||||||
struct open_file *f;
|
|
||||||
{
|
{
|
||||||
char *cp, *ncp;
|
char *cp, *ncp;
|
||||||
int c;
|
int c;
|
||||||
@ -516,18 +515,41 @@ ufs_open(upath, f)
|
|||||||
char namebuf[MAXPATHLEN+1];
|
char namebuf[MAXPATHLEN+1];
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
char *path = NULL;
|
char *path = NULL;
|
||||||
|
const char *dev;
|
||||||
|
ufs_mnt_t *mnt;
|
||||||
|
|
||||||
/* allocate file system specific data structure */
|
/* allocate file system specific data structure */
|
||||||
fp = malloc(sizeof(struct file));
|
errno = 0;
|
||||||
bzero(fp, sizeof(struct file));
|
fp = calloc(1, sizeof(struct file));
|
||||||
|
if (fp == NULL)
|
||||||
|
return (errno);
|
||||||
f->f_fsdata = (void *)fp;
|
f->f_fsdata = (void *)fp;
|
||||||
|
|
||||||
/* read super block */
|
dev = disk_fmtdev(f->f_devdata);
|
||||||
twiddle(1);
|
/* Is this device mounted? */
|
||||||
if ((rc = ffs_sbget(f, &fs, STDSB_NOHASHFAIL, "stand",
|
STAILQ_FOREACH(mnt, &mnt_list, um_link) {
|
||||||
ufs_use_sa_read)) != 0)
|
if (strcmp(dev, mnt->um_dev) == 0)
|
||||||
goto out;
|
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;
|
fp->f_fs = fs;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate indirect block levels.
|
* Calculate indirect block levels.
|
||||||
*/
|
*/
|
||||||
@ -671,14 +693,12 @@ ufs_open(upath, f)
|
|||||||
rc = 0;
|
rc = 0;
|
||||||
fp->f_seekp = 0;
|
fp->f_seekp = 0;
|
||||||
out:
|
out:
|
||||||
if (buf)
|
free(buf);
|
||||||
free(buf);
|
free(path);
|
||||||
if (path)
|
|
||||||
free(path);
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
if (fp->f_buf)
|
free(fp->f_buf);
|
||||||
free(fp->f_buf);
|
|
||||||
if (fp->f_fs != NULL) {
|
if (mnt == NULL && fp->f_fs != NULL) {
|
||||||
free(fp->f_fs->fs_csp);
|
free(fp->f_fs->fs_csp);
|
||||||
free(fp->f_fs->fs_si);
|
free(fp->f_fs->fs_si);
|
||||||
free(fp->f_fs);
|
free(fp->f_fs);
|
||||||
@ -711,27 +731,34 @@ ufs_use_sa_read(void *devfd, off_t loc, void **bufp, int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ufs_close(f)
|
ufs_close(struct open_file *f)
|
||||||
struct open_file *f;
|
|
||||||
{
|
{
|
||||||
|
ufs_mnt_t *mnt;
|
||||||
struct file *fp = (struct file *)f->f_fsdata;
|
struct file *fp = (struct file *)f->f_fsdata;
|
||||||
int level;
|
int level;
|
||||||
|
char *dev;
|
||||||
|
|
||||||
f->f_fsdata = (void *)0;
|
f->f_fsdata = NULL;
|
||||||
if (fp == (struct file *)0)
|
if (fp == NULL)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
for (level = 0; level < UFS_NIADDR; level++) {
|
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);
|
||||||
free(fp->f_buf);
|
|
||||||
if (fp->f_fs != NULL) {
|
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_csp);
|
||||||
free(fp->f_fs->fs_si);
|
free(fp->f_fs->fs_si);
|
||||||
free(fp->f_fs);
|
free(fp->f_fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(fp);
|
free(fp);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -741,11 +768,7 @@ ufs_close(f)
|
|||||||
* Cross block boundaries when necessary.
|
* Cross block boundaries when necessary.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ufs_read(f, start, size, resid)
|
ufs_read(struct open_file *f, void *start, size_t size, size_t *resid)
|
||||||
struct open_file *f;
|
|
||||||
void *start;
|
|
||||||
size_t size;
|
|
||||||
size_t *resid; /* out */
|
|
||||||
{
|
{
|
||||||
struct file *fp = (struct file *)f->f_fsdata;
|
struct file *fp = (struct file *)f->f_fsdata;
|
||||||
size_t csize;
|
size_t csize;
|
||||||
@ -783,11 +806,7 @@ ufs_read(f, start, size, resid)
|
|||||||
* extend the file.
|
* extend the file.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ufs_write(f, start, size, resid)
|
ufs_write(struct open_file *f, const void *start, size_t size, size_t *resid)
|
||||||
struct open_file *f;
|
|
||||||
const void *start;
|
|
||||||
size_t size;
|
|
||||||
size_t *resid; /* out */
|
|
||||||
{
|
{
|
||||||
struct file *fp = (struct file *)f->f_fsdata;
|
struct file *fp = (struct file *)f->f_fsdata;
|
||||||
size_t csize;
|
size_t csize;
|
||||||
@ -815,10 +834,7 @@ ufs_write(f, start, size, resid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static off_t
|
static off_t
|
||||||
ufs_seek(f, offset, where)
|
ufs_seek(struct open_file *f, off_t offset, int where)
|
||||||
struct open_file *f;
|
|
||||||
off_t offset;
|
|
||||||
int where;
|
|
||||||
{
|
{
|
||||||
struct file *fp = (struct file *)f->f_fsdata;
|
struct file *fp = (struct file *)f->f_fsdata;
|
||||||
|
|
||||||
@ -840,9 +856,7 @@ ufs_seek(f, offset, where)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ufs_stat(f, sb)
|
ufs_stat(struct open_file *f, struct stat *sb)
|
||||||
struct open_file *f;
|
|
||||||
struct stat *sb;
|
|
||||||
{
|
{
|
||||||
struct file *fp = (struct file *)f->f_fsdata;
|
struct file *fp = (struct file *)f->f_fsdata;
|
||||||
|
|
||||||
@ -894,3 +908,59 @@ ufs_readdir(struct open_file *f, struct dirent *d)
|
|||||||
strcpy(d->d_name, dp->d_name);
|
strcpy(d->d_name, dp->d_name);
|
||||||
return (0);
|
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);
|
||||||
|
}
|
||||||
|
@ -58,6 +58,8 @@ static int zfs_read(struct open_file *f, void *buf, size_t size, size_t *resid);
|
|||||||
static off_t zfs_seek(struct open_file *f, off_t offset, int where);
|
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_stat(struct open_file *f, struct stat *sb);
|
||||||
static int zfs_readdir(struct open_file *f, struct dirent *d);
|
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,
|
static void zfs_bootenv_initial(const char *envname, spa_t *spa,
|
||||||
const char *name, const char *dsname, int checkpoint);
|
const char *name, const char *dsname, int checkpoint);
|
||||||
@ -67,14 +69,16 @@ static void zfs_checkpoints_initial(spa_t *spa, const char *name,
|
|||||||
struct devsw zfs_dev;
|
struct devsw zfs_dev;
|
||||||
|
|
||||||
struct fs_ops zfs_fsops = {
|
struct fs_ops zfs_fsops = {
|
||||||
"zfs",
|
.fs_name = "zfs",
|
||||||
zfs_open,
|
.fo_open = zfs_open,
|
||||||
zfs_close,
|
.fo_close = zfs_close,
|
||||||
zfs_read,
|
.fo_read = zfs_read,
|
||||||
null_write,
|
.fo_write = null_write,
|
||||||
zfs_seek,
|
.fo_seek = zfs_seek,
|
||||||
zfs_stat,
|
.fo_stat = zfs_stat,
|
||||||
zfs_readdir
|
.fo_readdir = zfs_readdir,
|
||||||
|
.fo_mount = zfs_mount,
|
||||||
|
.fo_unmount = zfs_unmount
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -362,6 +366,74 @@ zfs_readdir(struct open_file *f, struct dirent *d)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
static int
|
||||||
vdev_read(vdev_t *vdev, void *priv, off_t offset, void *buf, size_t bytes)
|
vdev_read(vdev_t *vdev, void *priv, off_t offset, void *buf, size_t bytes)
|
||||||
{
|
{
|
||||||
@ -1503,32 +1575,45 @@ zfs_dev_open(struct open_file *f, ...)
|
|||||||
if ((spa = spa_find_by_dev(dev)) == NULL)
|
if ((spa = spa_find_by_dev(dev)) == NULL)
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
|
|
||||||
mount = malloc(sizeof(*mount));
|
STAILQ_FOREACH(mount, &zfsmount, next) {
|
||||||
|
if (spa->spa_guid == mount->spa->spa_guid)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = 0;
|
||||||
|
/* This device is not set as currdev, mount us private copy. */
|
||||||
if (mount == NULL)
|
if (mount == NULL)
|
||||||
rv = ENOMEM;
|
rv = zfs_mount(zfs_fmtdev(dev), NULL, (void **)&mount);
|
||||||
else
|
|
||||||
rv = zfs_mount(spa, dev->root_guid, mount);
|
if (rv == 0) {
|
||||||
if (rv != 0) {
|
f->f_devdata = mount;
|
||||||
free(mount);
|
free(dev);
|
||||||
return (rv);
|
|
||||||
}
|
}
|
||||||
if (mount->objset.os_type != DMU_OST_ZFS) {
|
return (rv);
|
||||||
printf("Unexpected object set type %ju\n",
|
|
||||||
(uintmax_t)mount->objset.os_type);
|
|
||||||
free(mount);
|
|
||||||
return (EIO);
|
|
||||||
}
|
|
||||||
f->f_devdata = mount;
|
|
||||||
free(dev);
|
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
zfs_dev_close(struct open_file *f)
|
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);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,11 +47,15 @@ extern int zstd_init(void);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct zfsmount {
|
struct zfsmount {
|
||||||
const spa_t *spa;
|
char *path;
|
||||||
objset_phys_t objset;
|
const spa_t *spa;
|
||||||
uint64_t rootobj;
|
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
|
* The indirect_child_t represents the vdev that we will read from, when we
|
||||||
@ -3321,7 +3325,7 @@ zfs_get_root(const spa_t *spa, uint64_t *objid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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;
|
mount->spa = spa;
|
||||||
|
@ -195,12 +195,12 @@ beri_arch_fmtdev(void *vdev)
|
|||||||
int
|
int
|
||||||
beri_arch_setcurrdev(struct env_var *ev, int flags, const void *value)
|
beri_arch_setcurrdev(struct env_var *ev, int flags, const void *value)
|
||||||
{
|
{
|
||||||
struct disk_devdesc *ncurr;
|
struct disk_devdesc *ncurr;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
if ((rv = beri_arch_parsedev(&ncurr, value, NULL)) != 0)
|
if ((rv = beri_arch_parsedev(&ncurr, value, NULL)) != 0)
|
||||||
return(rv);
|
return (rv);
|
||||||
free(ncurr);
|
free(ncurr);
|
||||||
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
|
|
||||||
return(0);
|
return (mount_currdev(ev, flags, value));
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,6 @@ ssize_t kboot_copyout(vm_offset_t src, void *dest, const size_t len);
|
|||||||
ssize_t kboot_readin(readin_handle_t fd, vm_offset_t dest, const size_t len);
|
ssize_t kboot_readin(readin_handle_t fd, vm_offset_t dest, const size_t len);
|
||||||
int kboot_autoload(void);
|
int kboot_autoload(void);
|
||||||
uint64_t kboot_loadaddr(u_int type, void *data, uint64_t addr);
|
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);
|
static void kboot_kseg_get(int *nseg, void **ptr);
|
||||||
|
|
||||||
extern int command_fdt_internal(int argc, char *argv[]);
|
extern int command_fdt_internal(int argc, char *argv[]);
|
||||||
|
@ -137,6 +137,9 @@ main(int (*openfirm)(void *))
|
|||||||
*/
|
*/
|
||||||
cons_probe();
|
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.
|
* March through the device switch probing for things.
|
||||||
*/
|
*/
|
||||||
|
@ -475,6 +475,9 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
meminfo();
|
meminfo();
|
||||||
|
|
||||||
|
/* Set up currdev variable to have hooks in place. */
|
||||||
|
env_setenv("currdev", EV_VOLATILE, "", uboot_setcurrdev, env_nounset);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enumerate U-Boot devices
|
* Enumerate U-Boot devices
|
||||||
*/
|
*/
|
||||||
|
@ -195,6 +195,6 @@ uboot_setcurrdev(struct env_var *ev, int flags, const void *value)
|
|||||||
if ((rv = uboot_parsedev(&ncurr, value, NULL)) != 0)
|
if ((rv = uboot_parsedev(&ncurr, value, NULL)) != 0)
|
||||||
return (rv);
|
return (rv);
|
||||||
free(ncurr);
|
free(ncurr);
|
||||||
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
|
|
||||||
return (0);
|
return (mount_currdev(ev, flags, value));
|
||||||
}
|
}
|
||||||
|
@ -222,6 +222,6 @@ userboot_setcurrdev(struct env_var *ev, int flags, const void *value)
|
|||||||
if ((rv = userboot_parsedev(&ncurr, value, NULL)) != 0)
|
if ((rv = userboot_parsedev(&ncurr, value, NULL)) != 0)
|
||||||
return (rv);
|
return (rv);
|
||||||
free(ncurr);
|
free(ncurr);
|
||||||
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
|
|
||||||
return (0);
|
return (mount_currdev(ev, flags, value));
|
||||||
}
|
}
|
||||||
|
@ -159,6 +159,10 @@ loader_main(struct loader_callbacks *cb, void *arg, int version, int ndisks)
|
|||||||
*/
|
*/
|
||||||
cons_probe();
|
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);
|
printf("\n%s", bootprog_info);
|
||||||
#if 0
|
#if 0
|
||||||
printf("Memory: %ld k\n", memsize() / 1024);
|
printf("Memory: %ld k\n", memsize() / 1024);
|
||||||
|
Loading…
Reference in New Issue
Block a user