FreeBSD/sys/fs/msdosfs/msdosfs_vfsops.c
/*
 * mp - path - addr in user space of mount point (ie /usr or whatever)
 * data - addr in user space of mount params including the name of the block
 * special file to treat as a filesystem.
 */
addr in user space of mount point
data - addr in user space of mount params including the name of the block
special file to treat as a filesystem.
addr in user space of mount point data - addr in user space of mount params including the name of the block special file to treat as a filesystem .
static int
msdosfs_mount(struct mount *mp)
{
	struct vnode *devvp;	  
	struct thread *td;
	struct msdosfsmount *pmp = NULL;
	struct nameidata ndp;
	int error, flags;
	accmode_t accmode;
	char *from;
	td = curthread;
	if (vfs_filteropt(mp->mnt_optnew, msdosfs_opts))
		return (EINVAL);
	if (mp->mnt_flag & MNT_UPDATE) {
		pmp = VFSTOMSDOSFS(mp);
		if (vfs_flagopt(mp->mnt_optnew, "export", NULL, 0)) {
			if ((pmp->pm_flags & MSDOSFS_LARGEFS) != 0) {
				vfs_mount_error(mp,
				    "MSDOSFS_LARGEFS flag set, cannot export");
				return (EOPNOTSUPP);
			}
		}
		if (!(pmp->pm_flags & MSDOSFSMNT_RONLY) &&
		    vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0)) {
			error = VFS_SYNC(mp, MNT_WAIT);
			if (error)
				return (error);
			flags = WRITECLOSE;
			if (mp->mnt_flag & MNT_FORCE)
				flags |= FORCECLOSE;
			error = vflush(mp, 0, flags, td);
			if (error)
				return (error);
			error = markvoldirty(pmp, 0);
			if (error) {
				(void)markvoldirty(pmp, 1);
				return (error);
			}
			g_topology_lock();
			error = g_access(pmp->pm_cp, 0, -1, 0);
			g_topology_unlock();
			if (error) {
				(void)markvoldirty(pmp, 1);
				return (error);
			}
			pmp->pm_fmod = 0;
			pmp->pm_flags |= MSDOSFSMNT_RONLY;
			MNT_ILOCK(mp);
			mp->mnt_flag |= MNT_RDONLY;
			MNT_IUNLOCK(mp);
		} else if ((pmp->pm_flags & MSDOSFSMNT_RONLY) &&
		    !vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0)) {
			devvp = pmp->pm_devvp;
			vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
			error = VOP_ACCESS(devvp, VREAD | VWRITE,
			    td->td_ucred, td);
			if (error)
				error = priv_check(td, PRIV_VFS_MOUNT_PERM);
			if (error) {
				VOP_UNLOCK(devvp, 0);
				return (error);
			}
			VOP_UNLOCK(devvp, 0);
			g_topology_lock();
			error = g_access(pmp->pm_cp, 0, 1, 0);
			g_topology_unlock();
			if (error)
				return (error);
			pmp->pm_fmod = 1;
			pmp->pm_flags &= ~MSDOSFSMNT_RONLY;
			MNT_ILOCK(mp);
			mp->mnt_flag &= ~MNT_RDONLY;
			MNT_IUNLOCK(mp);
			error = markvoldirty(pmp, 1);
			if (error)
				return (error); 
		}
	}
	if (vfs_getopt(mp->mnt_optnew, "from", (void **)&from, NULL))
		return (EINVAL);
	NDINIT(&ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, from, td);
	error = namei(&ndp);
	if (error)
		return (error);
	devvp = ndp.ni_vp;
	NDFREE(&ndp, NDF_ONLY_PNBUF);
	if (!vn_isdisk(devvp, &error)) {
		vput(devvp);
		return (error);
	}
	accmode = VREAD;
	if ((mp->mnt_flag & MNT_RDONLY) == 0)
		accmode |= VWRITE;
	error = VOP_ACCESS(devvp, accmode, td->td_ucred, td);
	if (error)
		error = priv_check(td, PRIV_VFS_MOUNT_PERM);
	if (error) {
		vput(devvp);
		return (error);
	}
	if ((mp->mnt_flag & MNT_UPDATE) == 0) {
		error = mountmsdosfs(devvp, mp);
#ifdef MSDOSFS_DEBUG		
		pmp = VFSTOMSDOSFS(mp);
#endif
	} else {
		vput(devvp);
		if (devvp != pmp->pm_devvp)
			return (EINVAL);	
	}
	if (error) {
		vrele(devvp);
		return (error);
	}
	error = update_mp(mp, td);
	if (error) {
		if ((mp->mnt_flag & MNT_UPDATE) == 0)
			msdosfs_unmount(mp, MNT_FORCE);
		return error;
	}
	vfs_mountedfrom(mp, from);
#ifdef MSDOSFS_DEBUG
	printf("msdosfs_mount(): mp %p, pmp %p, inusemap %p\n", mp, pmp, pmp->pm_inusemap);
#endif
	return (0);
}
static int msdosfs_mount ( struct mount * mp ) { struct vnode * devvp ; struct thread * td ; struct msdosfsmount * pmp = NULL ; struct nameidata ndp ; int error , flags ; accmode_t accmode ; char * from ; td = curthread ; if ( vfs_filteropt ( mp -> mnt_optnew , msdosfs_opts ) ) return ( EINVAL ) ; if ( mp -> mnt_flag & MNT_UPDATE ) { pmp = VFSTOMSDOSFS ( mp ) ; if ( vfs_flagopt ( mp -> mnt_optnew , " " , NULL , 0 ) ) { if ( ( pmp -> pm_flags & MSDOSFS_LARGEFS ) != 0 ) { vfs_mount_error ( mp , " " ) ; return ( EOPNOTSUPP ) ; } } if ( ! ( pmp -> pm_flags & MSDOSFSMNT_RONLY ) && vfs_flagopt ( mp -> mnt_optnew , " " , NULL , 0 ) ) { error = VFS_SYNC ( mp , MNT_WAIT ) ; if ( error ) return ( error ) ; flags = WRITECLOSE ; if ( mp -> mnt_flag & MNT_FORCE ) flags |= FORCECLOSE ; error = vflush ( mp , 0 , flags , td ) ; if ( error ) return ( error ) ; error = markvoldirty ( pmp , 0 ) ; if ( error ) { ( void ) markvoldirty ( pmp , 1 ) ; return ( error ) ; } g_topology_lock ( ) ; error = g_access ( pmp -> pm_cp , 0 , -1 , 0 ) ; g_topology_unlock ( ) ; if ( error ) { ( void ) markvoldirty ( pmp , 1 ) ; return ( error ) ; } pmp -> pm_fmod = 0 ; pmp -> pm_flags |= MSDOSFSMNT_RONLY ; MNT_ILOCK ( mp ) ; mp -> mnt_flag |= MNT_RDONLY ; MNT_IUNLOCK ( mp ) ; } else if ( ( pmp -> pm_flags & MSDOSFSMNT_RONLY ) && ! vfs_flagopt ( mp -> mnt_optnew , " " , NULL , 0 ) ) { devvp = pmp -> pm_devvp ; vn_lock ( devvp , LK_EXCLUSIVE | LK_RETRY ) ; error = VOP_ACCESS ( devvp , VREAD | VWRITE , td -> td_ucred , td ) ; if ( error ) error = priv_check ( td , PRIV_VFS_MOUNT_PERM ) ; if ( error ) { VOP_UNLOCK ( devvp , 0 ) ; return ( error ) ; } VOP_UNLOCK ( devvp , 0 ) ; g_topology_lock ( ) ; error = g_access ( pmp -> pm_cp , 0 , 1 , 0 ) ; g_topology_unlock ( ) ; if ( error ) return ( error ) ; pmp -> pm_fmod = 1 ; pmp -> pm_flags &= ~ MSDOSFSMNT_RONLY ; MNT_ILOCK ( mp ) ; mp -> mnt_flag &= ~ MNT_RDONLY ; MNT_IUNLOCK ( mp ) ; error = markvoldirty ( pmp , 1 ) ; if ( error ) return ( error ) ; } } if ( vfs_getopt ( mp -> mnt_optnew , " " , ( void * * ) & from , NULL ) ) return ( EINVAL ) ; NDINIT ( & ndp , LOOKUP , FOLLOW | LOCKLEAF , UIO_SYSSPACE , from , td ) ; error = namei ( & ndp ) ; if ( error ) return ( error ) ; devvp = ndp . ni_vp ; NDFREE ( & ndp , NDF_ONLY_PNBUF ) ; if ( ! vn_isdisk ( devvp , & error ) ) { vput ( devvp ) ; return ( error ) ; } accmode = VREAD ; if ( ( mp -> mnt_flag & MNT_RDONLY ) == 0 ) accmode |= VWRITE ; error = VOP_ACCESS ( devvp , accmode , td -> td_ucred , td ) ; if ( error ) error = priv_check ( td , PRIV_VFS_MOUNT_PERM ) ; if ( error ) { vput ( devvp ) ; return ( error ) ; } if ( ( mp -> mnt_flag & MNT_UPDATE ) == 0 ) { error = mountmsdosfs ( devvp , mp ) ; #ifdef MSDOSFS_DEBUG pmp = VFSTOMSDOSFS ( mp ) ; #endif } else { vput ( devvp ) ; if ( devvp != pmp -> pm_devvp ) return ( EINVAL ) ; } if ( error ) { vrele ( devvp ) ; return ( error ) ; } error = update_mp ( mp , td ) ; if ( error ) { if ( ( mp -> mnt_flag & MNT_UPDATE ) == 0 ) msdosfs_unmount ( mp , MNT_FORCE ) ; return error ; } vfs_mountedfrom ( mp , from ) ; #ifdef MSDOSFS_DEBUG printf ( " \n " , mp , pmp , pmp -> pm_inusemap ) ; #endif return ( 0 ) ; }
mp - path - addr in user space of mount point (ie /usr or whatever)
 data - addr in user space of mount params including the name of the block
 special file to treat as a filesystem.
mp - path - addr in user space of mount point ( ie / usr or whatever ) data - addr in user space of mount params including the name of the block special file to treat as a filesystem .
/* vnode for blk device to mount */ /* msdosfs specific mount control block */ /*
	 * If updating, check whether changing from read-only to
	 * read/write; if there is no device name, that's all we do.
	 */ /*
			 * Forbid export requests if filesystem has
			 * MSDOSFS_LARGEFS flag set.
			 */ /*
			 * Now the volume is clean.  Mark it so while the
			 * device is still rw.
			 */ /* Downgrade the device from rw to ro. */ /*
			 * Backing out after an error was painful in the
			 * above.  Now we are committed to succeeding.
			 */ /*
			 * If upgrade to read-write by non-root, then verify
			 * that user has necessary permissions on the device.
			 */ /* Now that the volume is modifiable, mark it dirty. */ /*
	 * Not an update, or updating the name: look up the name
	 * and verify that it refers to a sensible disk device.
	 */ /*
	 * If mount by non-root, then verify that user has necessary
	 * permissions on the device.
	 */ /* only needed for the printf below */ /* XXX needs translation */