NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, SCARG(uap, path), p);
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath, p);
sys_mount(p, v, retval)	struct proc *p;	void *v;	register_t *retval;{	register struct sys_mount_args /* {		syscallarg(char *) type;		syscallarg(char *) path;		syscallarg(int) flags;		syscallarg(void *) data;	} */ *uap = v;	register struct vnode *vp;	register struct mount *mp;	int error, flag = 0;#ifdef COMPAT_43	u_long fstypenum = 0;#endif	char fstypename[MFSNAMELEN];	struct vattr va;	struct nameidata nd;	struct vfsconf *vfsp;	struct timeval tv;	if (usermount == 0 && (error = suser(p->p_ucred, &p->p_acflag)))		return (error);	/*	 * Get vnode to be covered	 */	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,	    SCARG(uap, path), p);	if ((error = namei(&nd)) != 0)		return (error);	vp = nd.ni_vp;	if (SCARG(uap, flags) & MNT_UPDATE) {		if ((vp->v_flag & VROOT) == 0) {			vput(vp);			return (EINVAL);		}		mp = vp->v_mount;		flag = mp->mnt_flag;		/*		 * We only allow the filesystem to be reloaded if it		 * is currently mounted read-only.		 */		if ((SCARG(uap, flags) & MNT_RELOAD) &&		    ((mp->mnt_flag & MNT_RDONLY) == 0)) {			vput(vp);			return (EOPNOTSUPP);	/* Needs translation */		}		mp->mnt_flag |=		    SCARG(uap, flags) & (MNT_RELOAD | MNT_UPDATE);		/*		 * Only root, or the user that did the original mount is		 * permitted to update it.		 */		if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&		    (error = suser(p->p_ucred, &p->p_acflag))) {			vput(vp);			return (error);		}		/*		 * Do not allow NFS export by non-root users. Silently		 * enforce MNT_NOSUID and MNT_NODEV for non-root users.		 */		if (p->p_ucred->cr_uid != 0) {			if (SCARG(uap, flags) & MNT_EXPORTED) {				vput(vp);				return (EPERM);			}			SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;		}		VOP_UNLOCK(vp, 0, p);		goto update;	}	/*	 * If the user is not root, ensure that they own the directory	 * onto which we are attempting to mount.	 */	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) ||	    (va.va_uid != p->p_ucred->cr_uid &&	    (error = suser(p->p_ucred, &p->p_acflag)))) {		vput(vp);		return (error);	}	/*	 * Do not allow NFS export by non-root users. Silently	 * enforce MNT_NOSUID and MNT_NODEV for non-root users.	 */	if (p->p_ucred->cr_uid != 0) {		if (SCARG(uap, flags) & MNT_EXPORTED) {			vput(vp);			return (EPERM);		}		SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;	}	if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)		return (error);	if (vp->v_type != VDIR) {		vput(vp);		return (ENOTDIR);	}	error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL);	if (error) {#ifdef COMPAT_43		/*		 * Historically filesystem types were identified by number.		 * If we get an integer for the filesystem type instead of a		 * string, we check to see if it matches one of the historic		 * filesystem types.		 */		fstypenum = (u_long)SCARG(uap, type);		for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)			if (vfsp->vfc_typenum == fstypenum)				break;		if (vfsp == NULL) {			vput(vp);			return (ENODEV);		}		strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN);#else		vput(vp);		return (error);#endif	}	for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) {		if (!strcmp(vfsp->vfc_name, fstypename))			break;	}	if (vfsp == NULL) {		vput(vp);		return (EOPNOTSUPP);	}	if (vp->v_mountedhere != NULL) {		vput(vp);		return (EBUSY);	}	/*	 * Allocate and initialize the file system.	 */	mp = (struct mount *)malloc((u_long)sizeof(struct mount),		M_MOUNT, M_WAITOK);	bzero((char *)mp, (u_long)sizeof(struct mount));	lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0);	vfs_busy(mp, LK_NOWAIT, 0, p);	mp->mnt_op = vfsp->vfc_vfsops;	mp->mnt_vfc = vfsp;	mp->mnt_flag |= (vfsp->vfc_flags & MNT_VISFLAGMASK);	strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);	mp->mnt_vnodecovered = vp;	mp->mnt_stat.f_owner = p->p_ucred->cr_uid;update:	/*	 * Set the mount level flags.	 */	if (SCARG(uap, flags) & MNT_RDONLY)		mp->mnt_flag |= MNT_RDONLY;	else if (mp->mnt_flag & MNT_RDONLY)		mp->mnt_flag |= MNT_WANTRDWR;	mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |	    MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_SOFTDEP |	    MNT_NOATIME | MNT_FORCE);	mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |	    MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC |	    MNT_SOFTDEP | MNT_NOATIME | MNT_FORCE);	/*	 * Mount the filesystem.	 */	error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);	if (!error) {		microtime(&tv);		mp->mnt_stat.f_ctime = tv.tv_sec;	}	if (mp->mnt_flag & MNT_UPDATE) {		vrele(vp);		if (mp->mnt_flag & MNT_WANTRDWR)			mp->mnt_flag &= ~MNT_RDONLY;		mp->mnt_flag &=~		    (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);		if (error)			mp->mnt_flag = flag; 		if ((mp->mnt_flag & MNT_RDONLY) == 0) { 			if (mp->mnt_syncer == NULL) 				error = vfs_allocate_syncvnode(mp); 		} else { 			if (mp->mnt_syncer != NULL) 				vgone(mp->mnt_syncer); 			mp->mnt_syncer = NULL; 		}		vfs_unbusy(mp, p);		return (error);	}	vp->v_mountedhere = mp;	/*	 * Put the new filesystem on the mount list after root.	 */	cache_purge(vp);	if (!error) {		vfsp->vfc_refcount++;		simple_lock(&mountlist_slock);		CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);		simple_unlock(&mountlist_slock);		checkdirs(vp);		VOP_UNLOCK(vp, 0, p); 		if ((mp->mnt_flag & MNT_RDONLY) == 0) 			error = vfs_allocate_syncvnode(mp);		vfs_unbusy(mp, p);		(void) VFS_STATFS(mp, &mp->mnt_stat, p);		if ((error = VFS_START(mp, 0, p)) != 0)			vrele(vp);	} else {		mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;		vfs_unbusy(mp, p);		free((caddr_t)mp, M_MOUNT);		vput(vp);	}	return (error);}