FreeBSD/sys/kern/vfs_mount.c
/*
 * vfs_domount_first(): first file system mount (not update)
 */
first file system mount (not update)
first file system mount ( not update )
static int
vfs_domount_first(
	struct thread *td,		
	struct vfsconf *vfsp,		
	char *fspath,			
	struct vnode *vp,		
	uint64_t fsflags,		
	struct vfsoptlist **optlist	
	)
{
	struct vattr va;
	struct mount *mp;
	struct vnode *newdp;
	int error;
	ASSERT_VOP_ELOCKED(vp, __func__);
	KASSERT((fsflags & MNT_UPDATE) == 0, ("MNT_UPDATE shouldn't be here"));
	error = VOP_GETATTR(vp, &va, td->td_ucred);
	if (error == 0 && va.va_uid != td->td_ucred->cr_uid)
		error = priv_check_cred(td->td_ucred, PRIV_VFS_ADMIN, 0);
	if (error == 0)
		error = vinvalbuf(vp, V_SAVE, 0, 0);
	if (error == 0 && vp->v_type != VDIR)
		error = ENOTDIR;
	if (error == 0) {
		VI_LOCK(vp);
		if ((vp->v_iflag & VI_MOUNT) == 0 && vp->v_mountedhere == NULL)
			vp->v_iflag |= VI_MOUNT;
		else
			error = EBUSY;
		VI_UNLOCK(vp);
	}
	if (error != 0) {
		vput(vp);
		return (error);
	}
	VOP_UNLOCK(vp, 0);
	mp = vfs_mount_alloc(vp, vfsp, fspath, td->td_ucred);
	mp->mnt_optnew = *optlist;
	mp->mnt_flag = (fsflags & (MNT_UPDATEMASK | MNT_ROOTFS | MNT_RDONLY));
	error = VFS_MOUNT(mp);
	if (error != 0) {
		vfs_unbusy(mp);
		vfs_mount_destroy(mp);
		VI_LOCK(vp);
		vp->v_iflag &= ~VI_MOUNT;
		VI_UNLOCK(vp);
		vrele(vp);
		return (error);
	}
	if (mp->mnt_opt != NULL)
		vfs_freeopts(mp->mnt_opt);
	mp->mnt_opt = mp->mnt_optnew;
	*optlist = NULL;
	(void)VFS_STATFS(mp, &mp->mnt_stat);
	mp->mnt_optnew = NULL;
	MNT_ILOCK(mp);
	if ((mp->mnt_flag & MNT_ASYNC) != 0 &&
	    (mp->mnt_kern_flag & MNTK_NOASYNC) == 0)
		mp->mnt_kern_flag |= MNTK_ASYNC;
	else
		mp->mnt_kern_flag &= ~MNTK_ASYNC;
	MNT_IUNLOCK(mp);
	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
	cache_purge(vp);
	VI_LOCK(vp);
	vp->v_iflag &= ~VI_MOUNT;
	VI_UNLOCK(vp);
	vp->v_mountedhere = mp;
	mtx_lock(&mountlist_mtx);
	TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
	mtx_unlock(&mountlist_mtx);
	vfs_event_signal(NULL, VQ_MOUNT, 0);
	if (VFS_ROOT(mp, LK_EXCLUSIVE, &newdp))
		panic("mount: lost mount");
	VOP_UNLOCK(vp, 0);
	EVENTHANDLER_INVOKE(vfs_mounted, mp, newdp, td);
	VOP_UNLOCK(newdp, 0);
	mountcheckdirs(vp, newdp);
	vrele(newdp);
	if ((mp->mnt_flag & MNT_RDONLY) == 0)
		vfs_allocate_syncvnode(mp);
	vfs_unbusy(mp);
	return (0);
}
static int vfs_domount_first ( struct thread * td , struct vfsconf * vfsp , char * fspath , struct vnode * vp , uint64_t fsflags , struct vfsoptlist * * optlist ) { struct vattr va ; struct mount * mp ; struct vnode * newdp ; int error ; ASSERT_VOP_ELOCKED ( vp , __func__ ) ; KASSERT ( ( fsflags & MNT_UPDATE ) == 0 , ( " " ) ) ; error = VOP_GETATTR ( vp , & va , td -> td_ucred ) ; if ( error == 0 && va . va_uid != td -> td_ucred -> cr_uid ) error = priv_check_cred ( td -> td_ucred , PRIV_VFS_ADMIN , 0 ) ; if ( error == 0 ) error = vinvalbuf ( vp , V_SAVE , 0 , 0 ) ; if ( error == 0 && vp -> v_type != VDIR ) error = ENOTDIR ; if ( error == 0 ) { VI_LOCK ( vp ) ; if ( ( vp -> v_iflag & VI_MOUNT ) == 0 && vp -> v_mountedhere == NULL ) vp -> v_iflag |= VI_MOUNT ; else error = EBUSY ; VI_UNLOCK ( vp ) ; } if ( error != 0 ) { vput ( vp ) ; return ( error ) ; } VOP_UNLOCK ( vp , 0 ) ; mp = vfs_mount_alloc ( vp , vfsp , fspath , td -> td_ucred ) ; mp -> mnt_optnew = * optlist ; mp -> mnt_flag = ( fsflags & ( MNT_UPDATEMASK | MNT_ROOTFS | MNT_RDONLY ) ) ; error = VFS_MOUNT ( mp ) ; if ( error != 0 ) { vfs_unbusy ( mp ) ; vfs_mount_destroy ( mp ) ; VI_LOCK ( vp ) ; vp -> v_iflag &= ~ VI_MOUNT ; VI_UNLOCK ( vp ) ; vrele ( vp ) ; return ( error ) ; } if ( mp -> mnt_opt != NULL ) vfs_freeopts ( mp -> mnt_opt ) ; mp -> mnt_opt = mp -> mnt_optnew ; * optlist = NULL ; ( void ) VFS_STATFS ( mp , & mp -> mnt_stat ) ; mp -> mnt_optnew = NULL ; MNT_ILOCK ( mp ) ; if ( ( mp -> mnt_flag & MNT_ASYNC ) != 0 && ( mp -> mnt_kern_flag & MNTK_NOASYNC ) == 0 ) mp -> mnt_kern_flag |= MNTK_ASYNC ; else mp -> mnt_kern_flag &= ~ MNTK_ASYNC ; MNT_IUNLOCK ( mp ) ; vn_lock ( vp , LK_EXCLUSIVE | LK_RETRY ) ; cache_purge ( vp ) ; VI_LOCK ( vp ) ; vp -> v_iflag &= ~ VI_MOUNT ; VI_UNLOCK ( vp ) ; vp -> v_mountedhere = mp ; mtx_lock ( & mountlist_mtx ) ; TAILQ_INSERT_TAIL ( & mountlist , mp , mnt_list ) ; mtx_unlock ( & mountlist_mtx ) ; vfs_event_signal ( NULL , VQ_MOUNT , 0 ) ; if ( VFS_ROOT ( mp , LK_EXCLUSIVE , & newdp ) ) panic ( " " ) ; VOP_UNLOCK ( vp , 0 ) ; EVENTHANDLER_INVOKE ( vfs_mounted , mp , newdp , td ) ; VOP_UNLOCK ( newdp , 0 ) ; mountcheckdirs ( vp , newdp ) ; vrele ( newdp ) ; if ( ( mp -> mnt_flag & MNT_RDONLY ) == 0 ) vfs_allocate_syncvnode ( mp ) ; vfs_unbusy ( mp ) ; return ( 0 ) ; }
vfs_domount_first(): first file system mount (not update)
vfs_domount_first () : first file system mount ( not update )
/* Calling thread. */ /* File system type. */ /* Mount path. */ /* Vnode to be covered. */ /* Flags common to all filesystems. */ /* Options local to the filesystem. */ /*
	 * If the user is not root, ensure that they own the directory
	 * onto which we are attempting to mount.
	 */ /* Allocate and initialize the filesystem. */ /* XXXMAC: pass to vfs_mount_alloc? */ /* Set the mount level flags. */ /*
	 * Mount the filesystem.
	 * XXX The final recipients of VFS_MOUNT just overwrite the ndp they
	 * get.  No freeing of cn_pnbuf.
	 */ /*
	 * Prevent external consumers of mount options from reading mnt_optnew.
	 */ /* Place the new filesystem at the end of the mount list. */