+ /*
+ * Allocate and initialize the file system.
+ */
+ mp = (struct mount *)malloc((u_long)sizeof(struct mount),
+ M_MOUNT, M_WAITOK);
+ mp->m_op = vfssw[uap->type];
+ mp->m_flag = 0;
+ mp->m_exroot = 0;
+ mp->m_mounth = (struct vnode *)0;
+ if (error = vfs_lock(mp)) {
+ free((caddr_t)mp, M_MOUNT);
+ vput(vp);
+ RETURN (error);
+ }
+ if (vp->v_mountedhere != (struct mount *)0) {
+ vfs_unlock(mp);
+ free((caddr_t)mp, M_MOUNT);
+ vput(vp);
+ RETURN (EBUSY);
+ }
+ vp->v_mountedhere = mp;
+ mp->m_vnodecovered = vp;
+update:
+ /*
+ * Set the mount level flags.
+ */
+ if (uap->flags & M_RDONLY)
+ mp->m_flag |= M_RDONLY;
+ else
+ mp->m_flag &= ~M_RDONLY;
+ if (uap->flags & M_NOSUID)
+ mp->m_flag |= M_NOSUID;
+ else
+ mp->m_flag &= ~M_NOSUID;
+ if (uap->flags & M_NOEXEC)
+ mp->m_flag |= M_NOEXEC;
+ else
+ mp->m_flag &= ~M_NOEXEC;
+ if (uap->flags & M_NODEV)
+ mp->m_flag |= M_NODEV;
+ else
+ mp->m_flag &= ~M_NODEV;
+ if (uap->flags & M_SYNCHRONOUS)
+ mp->m_flag |= M_SYNCHRONOUS;
+ else
+ mp->m_flag &= ~M_SYNCHRONOUS;
+ /*
+ * Mount the filesystem.
+ */
+ error = VFS_MOUNT(mp, uap->dir, uap->data, ndp);
+ if (mp->m_flag & M_UPDATE) {
+ mp->m_flag &= ~M_UPDATE;
+ vrele(vp);
+ if (error)
+ mp->m_flag = flag;
+ RETURN (error);
+ }
+ /*
+ * Put the new filesystem on the mount list after root.
+ */
+ mp->m_next = rootfs->m_next;
+ mp->m_prev = rootfs;
+ rootfs->m_next = mp;
+ mp->m_next->m_prev = mp;
+ cache_purge(vp);
+ if (!error) {
+ VOP_UNLOCK(vp);
+ vfs_unlock(mp);
+ error = VFS_START(mp, 0);
+ } else {
+ vfs_remove(mp);
+ free((caddr_t)mp, M_MOUNT);
+ vput(vp);
+ }
+ RETURN (error);