#include <sys/param.h>
#include <sys/systm.h>
#include <sys/time.h>
#include <sys/proc.h>
#include <sys/buf.h>
#include <sys/mount.h>
#include <sys/signalvar.h>
#include <sys/vnode.h>
#include <sys/malloc.h>
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
#include <ufs/ufs/ufsmount.h>
#include <ufs/ufs/ufs_extern.h>
#include <ufs/ffs/fs.h>
#include <ufs/ffs/ffs_extern.h>
#include <ufs/mfs/mfsnode.h>
#include <ufs/mfs/mfs_extern.h>
static int mfs_minor;
const struct vfsops mfs_vfsops = {
.vfs_mount = mfs_mount,
.vfs_start = mfs_start,
.vfs_unmount = ffs_unmount,
.vfs_root = ufs_root,
.vfs_quotactl = ufs_quotactl,
.vfs_statfs = ffs_statfs,
.vfs_sync = ffs_sync,
.vfs_vget = ffs_vget,
.vfs_fhtovp = ffs_fhtovp,
.vfs_vptofh = ffs_vptofh,
.vfs_init = mfs_init,
.vfs_sysctl = ffs_sysctl,
.vfs_checkexp = mfs_checkexp,
};
int
mfs_mount(struct mount *mp, const char *path, void *data,
struct nameidata *ndp, struct proc *p)
{
struct vnode *devvp;
struct mfs_args *args = data;
struct ufsmount *ump;
struct fs *fs;
struct mfsnode *mfsp;
char fspec[MNAMELEN];
int flags, error;
if (mp->mnt_flag & MNT_UPDATE) {
ump = VFSTOUFS(mp);
fs = ump->um_fs;
if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
flags = WRITECLOSE;
if (mp->mnt_flag & MNT_FORCE)
flags |= FORCECLOSE;
error = ffs_flushfiles(mp, flags, p);
if (error)
return (error);
}
if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR))
fs->fs_ronly = 0;
#ifdef EXPORTMFS
if (args && args->fspec == NULL)
return (vfs_export(mp, &ump->um_export,
&args->export_info));
#endif
return (0);
}
error = copyinstr(args->fspec, fspec, sizeof(fspec), NULL);
if (error)
return (error);
error = getnewvnode(VT_MFS, NULL, &mfs_vops, &devvp);
if (error)
return (error);
devvp->v_type = VBLK;
if (checkalias(devvp, makedev(255, mfs_minor), NULL))
panic("mfs_mount: dup dev");
mfs_minor++;
mfsp = malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK | M_ZERO);
devvp->v_data = mfsp;
mfsp->mfs_baseoff = args->base;
mfsp->mfs_size = args->size;
mfsp->mfs_vnode = devvp;
mfsp->mfs_tid = p->p_tid;
bufq_init(&mfsp->mfs_bufq, BUFQ_FIFO);
if ((error = ffs_mountfs(devvp, mp, p)) != 0) {
mfsp->mfs_shutdown = 1;
vrele(devvp);
return (error);
}
ump = VFSTOUFS(mp);
fs = ump->um_fs;
memset(fs->fs_fsmnt, 0, sizeof(fs->fs_fsmnt));
strlcpy(fs->fs_fsmnt, path, sizeof(fs->fs_fsmnt));
memcpy(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN);
memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
strlcpy(mp->mnt_stat.f_mntfromname, fspec, MNAMELEN);
memset(mp->mnt_stat.f_mntfromspec, 0, MNAMELEN);
strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN);
memcpy(&mp->mnt_stat.mount_info.mfs_args, args, sizeof(*args));
return (0);
}
int
mfs_start(struct mount *mp, int flags, struct proc *p)
{
struct vnode *vp = VFSTOUFS(mp)->um_devvp;
struct mfsnode *mfsp = VTOMFS(vp);
struct buf *bp;
int sleepreturn = 0, sig;
struct sigctx ctx;
while (1) {
while (1) {
if (mfsp->mfs_shutdown == 1)
break;
bp = bufq_dequeue(&mfsp->mfs_bufq);
if (bp == NULL)
break;
mfs_doio(mfsp, bp);
wakeup(bp);
}
if (mfsp->mfs_shutdown == 1)
break;
if (sleepreturn != 0) {
sig = cursig(p, &ctx, 0);
if (vfs_busy(mp, VB_WRITE|VB_NOWAIT) ||
dounmount(mp, (sig == SIGKILL) ? MNT_FORCE : 0, p))
atomic_clearbits_int(&p->p_siglist,
sigmask(sig));
sleepreturn = 0;
continue;
}
sleepreturn = tsleep_nsec(vp, PWAIT | PCATCH, "mfsidl", INFSLP);
}
return (0);
}
int
mfs_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp,
struct ucred **credanonp)
{
return (EOPNOTSUPP);
}
int
mfs_init(struct vfsconf *vfsp)
{
return (ffs_init(vfsp));
}