xref: /csrg-svn/sys/kern/vfs_subr.c (revision 39045)
137488Smckusick /*
237488Smckusick  * Copyright (c) 1989 The Regents of the University of California.
337488Smckusick  * All rights reserved.
437488Smckusick  *
537488Smckusick  * Redistribution and use in source and binary forms are permitted
637488Smckusick  * provided that the above copyright notice and this paragraph are
737488Smckusick  * duplicated in all such forms and that any documentation,
837488Smckusick  * advertising materials, and other materials related to such
937488Smckusick  * distribution and use acknowledge that the software was developed
1037488Smckusick  * by the University of California, Berkeley.  The name of the
1137488Smckusick  * University may not be used to endorse or promote products derived
1237488Smckusick  * from this software without specific prior written permission.
1337488Smckusick  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1437488Smckusick  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1537488Smckusick  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1637488Smckusick  *
17*39045Smckusick  *	@(#)vfs_subr.c	7.6 (Berkeley) 09/05/89
1837488Smckusick  */
1937488Smckusick 
2037488Smckusick /*
2137488Smckusick  * External virtual filesystem routines
2237488Smckusick  */
2337488Smckusick 
2437488Smckusick #include "param.h"
2537488Smckusick #include "mount.h"
2637488Smckusick #include "time.h"
2737488Smckusick #include "vnode.h"
2838265Smckusick #include "namei.h"
2938265Smckusick #include "ucred.h"
3037488Smckusick #include "errno.h"
3137488Smckusick 
3237488Smckusick /*
3337488Smckusick  * Add a new mount point to the list of mounted filesystems.
3437488Smckusick  * Lock the filesystem so that namei will not cross into the
3537488Smckusick  * the tree below the covered vnode.
3637488Smckusick  */
3737488Smckusick vfs_add(mountedvp, mp, flags)
3837488Smckusick 	register struct vnode *mountedvp;
3937488Smckusick 	register struct mount *mp;
4037488Smckusick 	int flags;
4137488Smckusick {
4237488Smckusick 	register int error;
4337488Smckusick 
4437488Smckusick 	error = vfs_lock(mp);
4537488Smckusick 	if (error)
4637488Smckusick 		return (error);
4737488Smckusick 	if (mountedvp == (struct vnode *)0) {
4837488Smckusick 		/*
4937488Smckusick 		 * We are mounting the root filesystem.
5037488Smckusick 		 */
5137488Smckusick 		rootfs = mp;
5237488Smckusick 		mp->m_next = mp;
5337488Smckusick 		mp->m_prev = mp;
5437488Smckusick 	} else {
5537488Smckusick 		if (mountedvp->v_mountedhere != (struct mount *)0) {
5637488Smckusick 			vfs_unlock(mp);
5737488Smckusick 			return(EBUSY);
5837488Smckusick 		}
5937488Smckusick 		/*
6037488Smckusick 		 * Put the new filesystem on the mount list after root.
6137488Smckusick 		 */
6237488Smckusick 		mp->m_next = rootfs->m_next;
6337488Smckusick 		mp->m_prev = rootfs;
6437488Smckusick 		rootfs->m_next = mp;
6537488Smckusick 		mp->m_next->m_prev = mp;
6637488Smckusick 		mountedvp->v_mountedhere = mp;
6737488Smckusick 	}
6837488Smckusick 	mp->m_vnodecovered = mountedvp;
6937488Smckusick 	if (flags & M_RDONLY) {
7037488Smckusick 		mp->m_flag |= M_RDONLY;
7137488Smckusick 	} else {
7237488Smckusick 		mp->m_flag &= ~M_RDONLY;
7337488Smckusick 	}
7437488Smckusick 	if (flags & M_NOSUID) {
7537488Smckusick 		mp->m_flag |= M_NOSUID;
7637488Smckusick 	} else {
7737488Smckusick 		mp->m_flag &= ~M_NOSUID;
7837488Smckusick 	}
7937488Smckusick 	return (0);
8037488Smckusick }
8137488Smckusick 
8237488Smckusick /*
8337488Smckusick  * Remove a mount point from the list of mounted filesystems.
8437488Smckusick  * Unmount of the root is illegal.
8537488Smckusick  */
8637488Smckusick void
8737488Smckusick vfs_remove(mp)
8837488Smckusick 	register struct mount *mp;
8937488Smckusick {
9037488Smckusick 
9137488Smckusick 	if (mp == rootfs)
9237488Smckusick 		panic("vfs_remove: unmounting root");
9337488Smckusick 	mp->m_prev->m_next = mp->m_next;
9437488Smckusick 	mp->m_next->m_prev = mp->m_prev;
9537488Smckusick 	mp->m_vnodecovered->v_mountedhere = (struct mount *)0;
9637488Smckusick 	vfs_unlock(mp);
9737488Smckusick }
9837488Smckusick 
9937488Smckusick /*
10037488Smckusick  * Lock a filesystem.
10137488Smckusick  * Used to prevent access to it while mounting and unmounting.
10237488Smckusick  */
10337488Smckusick vfs_lock(mp)
10437488Smckusick 	register struct mount *mp;
10537488Smckusick {
10637488Smckusick 
107*39045Smckusick 	while(mp->m_flag & M_MLOCK) {
108*39045Smckusick 		mp->m_flag |= M_MWAIT;
109*39045Smckusick 		sleep((caddr_t)mp, PVFS);
110*39045Smckusick 	}
11137488Smckusick 	mp->m_flag |= M_MLOCK;
11237488Smckusick 	return (0);
11337488Smckusick }
11437488Smckusick 
11537488Smckusick /*
11637488Smckusick  * Unlock a locked filesystem.
11737488Smckusick  * Panic if filesystem is not locked.
11837488Smckusick  */
11937488Smckusick void
12037488Smckusick vfs_unlock(mp)
12137488Smckusick 	register struct mount *mp;
12237488Smckusick {
12337488Smckusick 
12437488Smckusick 	if ((mp->m_flag & M_MLOCK) == 0)
12537488Smckusick 		panic("vfs_unlock: locked fs");
12637488Smckusick 	mp->m_flag &= ~M_MLOCK;
12737488Smckusick 	if (mp->m_flag & M_MWAIT) {
12837488Smckusick 		mp->m_flag &= ~M_MWAIT;
12937488Smckusick 		wakeup((caddr_t)mp);
13037488Smckusick 	}
13137488Smckusick }
13237488Smckusick 
13337488Smckusick /*
13437488Smckusick  * Lookup a mount point by filesystem identifier.
13537488Smckusick  */
13637488Smckusick struct mount *
13737488Smckusick getvfs(fsid)
13837488Smckusick 	fsid_t *fsid;
13937488Smckusick {
14037488Smckusick 	register struct mount *mp;
14137488Smckusick 
14238288Smckusick 	mp = rootfs;
14338288Smckusick 	do {
14437488Smckusick 		if (mp->m_fsid.val[0] == fsid->val[0] &&
14537488Smckusick 		    mp->m_fsid.val[1] == fsid->val[1]) {
14638288Smckusick 			return (mp);
14737488Smckusick 		}
14838288Smckusick 		mp = mp->m_next;
14938288Smckusick 	} while (mp != rootfs);
15038288Smckusick 	return ((struct mount *)0);
15137488Smckusick }
15237488Smckusick 
15337488Smckusick /*
15437488Smckusick  * Set vnode attributes to VNOVAL
15537488Smckusick  */
15637488Smckusick void vattr_null(vap)
15737488Smckusick 	register struct vattr *vap;
15837488Smckusick {
15937488Smckusick 
16037488Smckusick 	vap->va_type = VNON;
16137488Smckusick 	vap->va_mode = vap->va_nlink = vap->va_uid = vap->va_gid =
16237488Smckusick 		vap->va_fsid = vap->va_fileid = vap->va_size =
16337488Smckusick 		vap->va_size1 = vap->va_blocksize = vap->va_rdev =
16437488Smckusick 		vap->va_bytes = vap->va_bytes1 =
16537488Smckusick 		vap->va_atime.tv_sec = vap->va_atime.tv_usec =
16637488Smckusick 		vap->va_mtime.tv_sec = vap->va_mtime.tv_usec =
16738258Smckusick 		vap->va_ctime.tv_sec = vap->va_ctime.tv_usec =
16838258Smckusick 		vap->va_flags = vap->va_gen = VNOVAL;
16937488Smckusick }
17038265Smckusick 
17138265Smckusick /*
17238265Smckusick  * Initialize a nameidata structure
17338265Smckusick  */
17438265Smckusick ndinit(ndp)
17538265Smckusick 	register struct nameidata *ndp;
17638265Smckusick {
17738265Smckusick 
17838265Smckusick 	bzero((caddr_t)ndp, sizeof(struct nameidata));
17938265Smckusick 	ndp->ni_iov = &ndp->ni_nd.nd_iovec;
18038265Smckusick 	ndp->ni_iovcnt = 1;
18138265Smckusick 	ndp->ni_base = (caddr_t)&ndp->ni_dent;
18238265Smckusick 	ndp->ni_rw = UIO_WRITE;
18338265Smckusick 	ndp->ni_segflg = UIO_SYSSPACE;
18438265Smckusick }
18538265Smckusick 
18638265Smckusick /*
18738265Smckusick  * Duplicate a nameidata structure
18838265Smckusick  */
18938265Smckusick nddup(ndp, newndp)
19038265Smckusick 	register struct nameidata *ndp, *newndp;
19138265Smckusick {
19238265Smckusick 
19338265Smckusick 	ndinit(newndp);
19438265Smckusick 	newndp->ni_cdir = ndp->ni_cdir;
19538348Smckusick 	VREF(newndp->ni_cdir);
19638265Smckusick 	newndp->ni_rdir = ndp->ni_rdir;
19738265Smckusick 	if (newndp->ni_rdir)
19838348Smckusick 		VREF(newndp->ni_rdir);
19938265Smckusick 	newndp->ni_cred = ndp->ni_cred;
20038265Smckusick 	crhold(newndp->ni_cred);
20138265Smckusick }
20238265Smckusick 
20338265Smckusick /*
20438265Smckusick  * Release a nameidata structure
20538265Smckusick  */
20638265Smckusick ndrele(ndp)
20738265Smckusick 	register struct nameidata *ndp;
20838265Smckusick {
20938265Smckusick 
21038265Smckusick 	vrele(ndp->ni_cdir);
21138265Smckusick 	if (ndp->ni_rdir)
21238265Smckusick 		vrele(ndp->ni_rdir);
21338265Smckusick 	crfree(ndp->ni_cred);
21438265Smckusick }
215