xref: /original-bsd/sys/kern/vfs_subr.c (revision 69360437)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)vfs_subr.c	7.4 (Berkeley) 06/24/89
18  */
19 
20 /*
21  * External virtual filesystem routines
22  */
23 
24 #include "param.h"
25 #include "mount.h"
26 #include "time.h"
27 #include "vnode.h"
28 #include "namei.h"
29 #include "ucred.h"
30 #include "errno.h"
31 
32 /*
33  * Add a new mount point to the list of mounted filesystems.
34  * Lock the filesystem so that namei will not cross into the
35  * the tree below the covered vnode.
36  */
37 vfs_add(mountedvp, mp, flags)
38 	register struct vnode *mountedvp;
39 	register struct mount *mp;
40 	int flags;
41 {
42 	register int error;
43 
44 	error = vfs_lock(mp);
45 	if (error)
46 		return (error);
47 	if (mountedvp == (struct vnode *)0) {
48 		/*
49 		 * We are mounting the root filesystem.
50 		 */
51 		rootfs = mp;
52 		mp->m_next = mp;
53 		mp->m_prev = mp;
54 	} else {
55 		if (mountedvp->v_mountedhere != (struct mount *)0) {
56 			vfs_unlock(mp);
57 			return(EBUSY);
58 		}
59 		/*
60 		 * Put the new filesystem on the mount list after root.
61 		 */
62 		mp->m_next = rootfs->m_next;
63 		mp->m_prev = rootfs;
64 		rootfs->m_next = mp;
65 		mp->m_next->m_prev = mp;
66 		mountedvp->v_mountedhere = mp;
67 	}
68 	mp->m_vnodecovered = mountedvp;
69 	if (flags & M_RDONLY) {
70 		mp->m_flag |= M_RDONLY;
71 	} else {
72 		mp->m_flag &= ~M_RDONLY;
73 	}
74 	if (flags & M_NOSUID) {
75 		mp->m_flag |= M_NOSUID;
76 	} else {
77 		mp->m_flag &= ~M_NOSUID;
78 	}
79 	return (0);
80 }
81 
82 /*
83  * Remove a mount point from the list of mounted filesystems.
84  * Unmount of the root is illegal.
85  */
86 void
87 vfs_remove(mp)
88 	register struct mount *mp;
89 {
90 
91 	if (mp == rootfs)
92 		panic("vfs_remove: unmounting root");
93 	mp->m_prev->m_next = mp->m_next;
94 	mp->m_next->m_prev = mp->m_prev;
95 	mp->m_vnodecovered->v_mountedhere = (struct mount *)0;
96 	vfs_unlock(mp);
97 }
98 
99 /*
100  * Lock a filesystem.
101  * Used to prevent access to it while mounting and unmounting.
102  */
103 vfs_lock(mp)
104 	register struct mount *mp;
105 {
106 
107 	if (mp->m_flag & M_MLOCK)
108 		return (EBUSY);
109 	mp->m_flag |= M_MLOCK;
110 	return (0);
111 }
112 
113 /*
114  * Unlock a locked filesystem.
115  * Panic if filesystem is not locked.
116  */
117 void
118 vfs_unlock(mp)
119 	register struct mount *mp;
120 {
121 
122 	if ((mp->m_flag & M_MLOCK) == 0)
123 		panic("vfs_unlock: locked fs");
124 	mp->m_flag &= ~M_MLOCK;
125 	if (mp->m_flag & M_MWAIT) {
126 		mp->m_flag &= ~M_MWAIT;
127 		wakeup((caddr_t)mp);
128 	}
129 }
130 
131 /*
132  * Lookup a mount point by filesystem identifier.
133  */
134 struct mount *
135 getvfs(fsid)
136 	fsid_t *fsid;
137 {
138 	register struct mount *mp;
139 
140 	mp = rootfs;
141 	do {
142 		if (mp->m_fsid.val[0] == fsid->val[0] &&
143 		    mp->m_fsid.val[1] == fsid->val[1]) {
144 			return (mp);
145 		}
146 		mp = mp->m_next;
147 	} while (mp != rootfs);
148 	return ((struct mount *)0);
149 }
150 
151 /*
152  * Set vnode attributes to VNOVAL
153  */
154 void vattr_null(vap)
155 	register struct vattr *vap;
156 {
157 
158 	vap->va_type = VNON;
159 	vap->va_mode = vap->va_nlink = vap->va_uid = vap->va_gid =
160 		vap->va_fsid = vap->va_fileid = vap->va_size =
161 		vap->va_size1 = vap->va_blocksize = vap->va_rdev =
162 		vap->va_bytes = vap->va_bytes1 =
163 		vap->va_atime.tv_sec = vap->va_atime.tv_usec =
164 		vap->va_mtime.tv_sec = vap->va_mtime.tv_usec =
165 		vap->va_ctime.tv_sec = vap->va_ctime.tv_usec =
166 		vap->va_flags = vap->va_gen = VNOVAL;
167 }
168 
169 /*
170  * Initialize a nameidata structure
171  */
172 ndinit(ndp)
173 	register struct nameidata *ndp;
174 {
175 
176 	bzero((caddr_t)ndp, sizeof(struct nameidata));
177 	ndp->ni_iov = &ndp->ni_nd.nd_iovec;
178 	ndp->ni_iovcnt = 1;
179 	ndp->ni_base = (caddr_t)&ndp->ni_dent;
180 	ndp->ni_rw = UIO_WRITE;
181 	ndp->ni_segflg = UIO_SYSSPACE;
182 }
183 
184 /*
185  * Duplicate a nameidata structure
186  */
187 nddup(ndp, newndp)
188 	register struct nameidata *ndp, *newndp;
189 {
190 
191 	ndinit(newndp);
192 	newndp->ni_cdir = ndp->ni_cdir;
193 	newndp->ni_cdir->v_count++;
194 	newndp->ni_rdir = ndp->ni_rdir;
195 	if (newndp->ni_rdir)
196 		newndp->ni_rdir->v_count++;
197 	newndp->ni_cred = ndp->ni_cred;
198 	crhold(newndp->ni_cred);
199 }
200 
201 /*
202  * Release a nameidata structure
203  */
204 ndrele(ndp)
205 	register struct nameidata *ndp;
206 {
207 
208 	vrele(ndp->ni_cdir);
209 	if (ndp->ni_rdir)
210 		vrele(ndp->ni_rdir);
211 	crfree(ndp->ni_cred);
212 }
213