get rid of all dependencies on ufs
[unix-history] / usr / src / sys / kern / vfs_subr.c
CommitLineData
3c4390e8
KM
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 *
36d09cb1 17 * @(#)vfs_subr.c 7.8 (Berkeley) %G%
3c4390e8
KM
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"
c60798ca
KM
28#include "namei.h"
29#include "ucred.h"
3c4390e8
KM
30#include "errno.h"
31
3c4390e8
KM
32/*
33 * Remove a mount point from the list of mounted filesystems.
34 * Unmount of the root is illegal.
35 */
36void
37vfs_remove(mp)
38 register struct mount *mp;
39{
40
41 if (mp == rootfs)
42 panic("vfs_remove: unmounting root");
43 mp->m_prev->m_next = mp->m_next;
44 mp->m_next->m_prev = mp->m_prev;
45 mp->m_vnodecovered->v_mountedhere = (struct mount *)0;
46 vfs_unlock(mp);
47}
48
49/*
50 * Lock a filesystem.
51 * Used to prevent access to it while mounting and unmounting.
52 */
53vfs_lock(mp)
54 register struct mount *mp;
55{
56
594501df
KM
57 while(mp->m_flag & M_MLOCK) {
58 mp->m_flag |= M_MWAIT;
59 sleep((caddr_t)mp, PVFS);
60 }
3c4390e8
KM
61 mp->m_flag |= M_MLOCK;
62 return (0);
63}
64
65/*
66 * Unlock a locked filesystem.
67 * Panic if filesystem is not locked.
68 */
69void
70vfs_unlock(mp)
71 register struct mount *mp;
72{
73
74 if ((mp->m_flag & M_MLOCK) == 0)
75 panic("vfs_unlock: locked fs");
76 mp->m_flag &= ~M_MLOCK;
77 if (mp->m_flag & M_MWAIT) {
78 mp->m_flag &= ~M_MWAIT;
79 wakeup((caddr_t)mp);
80 }
81}
82
83/*
84 * Lookup a mount point by filesystem identifier.
85 */
86struct mount *
87getvfs(fsid)
88 fsid_t *fsid;
89{
90 register struct mount *mp;
91
d713f801
KM
92 mp = rootfs;
93 do {
3c4390e8
KM
94 if (mp->m_fsid.val[0] == fsid->val[0] &&
95 mp->m_fsid.val[1] == fsid->val[1]) {
d713f801 96 return (mp);
3c4390e8 97 }
d713f801
KM
98 mp = mp->m_next;
99 } while (mp != rootfs);
100 return ((struct mount *)0);
3c4390e8
KM
101}
102
103/*
104 * Set vnode attributes to VNOVAL
105 */
106void vattr_null(vap)
107 register struct vattr *vap;
108{
109
110 vap->va_type = VNON;
111 vap->va_mode = vap->va_nlink = vap->va_uid = vap->va_gid =
112 vap->va_fsid = vap->va_fileid = vap->va_size =
113 vap->va_size1 = vap->va_blocksize = vap->va_rdev =
114 vap->va_bytes = vap->va_bytes1 =
115 vap->va_atime.tv_sec = vap->va_atime.tv_usec =
116 vap->va_mtime.tv_sec = vap->va_mtime.tv_usec =
8cf4d4fb
KM
117 vap->va_ctime.tv_sec = vap->va_ctime.tv_usec =
118 vap->va_flags = vap->va_gen = VNOVAL;
3c4390e8 119}
c60798ca
KM
120
121/*
122 * Initialize a nameidata structure
123 */
124ndinit(ndp)
125 register struct nameidata *ndp;
126{
127
128 bzero((caddr_t)ndp, sizeof(struct nameidata));
129 ndp->ni_iov = &ndp->ni_nd.nd_iovec;
130 ndp->ni_iovcnt = 1;
131 ndp->ni_base = (caddr_t)&ndp->ni_dent;
132 ndp->ni_rw = UIO_WRITE;
133 ndp->ni_segflg = UIO_SYSSPACE;
134}
135
136/*
137 * Duplicate a nameidata structure
138 */
139nddup(ndp, newndp)
140 register struct nameidata *ndp, *newndp;
141{
142
143 ndinit(newndp);
144 newndp->ni_cdir = ndp->ni_cdir;
8fe1c702 145 VREF(newndp->ni_cdir);
c60798ca
KM
146 newndp->ni_rdir = ndp->ni_rdir;
147 if (newndp->ni_rdir)
8fe1c702 148 VREF(newndp->ni_rdir);
c60798ca
KM
149 newndp->ni_cred = ndp->ni_cred;
150 crhold(newndp->ni_cred);
151}
152
153/*
154 * Release a nameidata structure
155 */
156ndrele(ndp)
157 register struct nameidata *ndp;
158{
159
160 vrele(ndp->ni_cdir);
161 if (ndp->ni_rdir)
162 vrele(ndp->ni_rdir);
163 crfree(ndp->ni_cred);
164}
36d09cb1
KM
165
166/*
167 * Routines having to do with the management of the vnode table.
168 */
169struct vnode *vfreeh, **vfreet;
170extern struct vnodeops dead_vnodeops;
171
172/*
173 * Build vnode free list.
174 */
175vhinit()
176{
177 register struct vnode *vp = vnode;
178
179 vfreeh = vp;
180 vfreet = &vp->v_freef;
181 vp->v_freeb = &vfreeh;
182 vp->v_op = &dead_vnodeops;
183 for (vp++; vp < vnodeNVNODE; vp++) {
184 *vfreet = vp;
185 vp->v_freeb = vfreet;
186 vfreet = &vp->v_freef;
187 vp->v_op = &dead_vnodeops;
188 }
189 vp--;
190 vp->v_freef = NULL;
191}
192
193/*
194 * Return the next vnode from the free list.
195 */
196getnewvnode(tag, mp, vops, vpp)
197 enum vtagtype tag;
198 struct mount *mp;
199 struct vnodeops *vops;
200 struct vnode **vpp;
201{
202 register struct vnode *vp, *vq;
203
204 if ((vp = vfreeh) == NULL) {
205 tablefull("vnode");
206 *vpp = 0;
207 return (ENFILE);
208 }
209 if (vp->v_count || VOP_RECLAIM(vp))
210 panic("free vnode isn't");
211 if (vq = vp->v_freef)
212 vq->v_freeb = &vfreeh;
213 vfreeh = vq;
214 vp->v_freef = NULL;
215 vp->v_freeb = NULL;
216 vp->v_type = VNON;
217 vp->v_flag = 0;
218 vp->v_shlockc = 0;
219 vp->v_exlockc = 0;
220 vp->v_socket = 0;
221 vp->v_op = vops;
222 cache_purge(vp);
223 vp->v_tag = tag;
224 vp->v_mount = mp;
225 insmntque(vp, mp);
226 VREF(vp);
227 *vpp = vp;
228 return (0);
229}
230
231/*
232 * Move a vnode from one mount queue to another.
233 */
234insmntque(vp, mp)
235 register struct vnode *vp;
236 register struct mount *mp;
237{
238 struct vnode *vq;
239
240 /*
241 * Delete from old mount point vnode list, if on one.
242 */
243 if (vp->v_mountb) {
244 if (vq = vp->v_mountf)
245 vq->v_mountb = vp->v_mountb;
246 *vp->v_mountb = vq;
247 }
248 /*
249 * Insert into list of vnodes for the new mount point, if available.
250 */
251 if (mp == NULL) {
252 vp->v_mountf = NULL;
253 vp->v_mountb = NULL;
254 return;
255 }
256 if (mp->m_mounth) {
257 vp->v_mountf = mp->m_mounth;
258 vp->v_mountb = &mp->m_mounth;
259 mp->m_mounth->v_mountb = &vp->v_mountf;
260 mp->m_mounth = vp;
261 } else {
262 mp->m_mounth = vp;
263 vp->v_mountb = &mp->m_mounth;
264 vp->v_mountf = NULL;
265 }
266}
267
268/*
269 * Grab a particular vnode from the free list.
270 */
271vget(vp)
272 register struct vnode *vp;
273{
274 register struct vnode *vq;
275
276 if (vq = vp->v_freef)
277 vq->v_freeb = vp->v_freeb;
278 else
279 vfreet = vp->v_freeb;
280 *vp->v_freeb = vq;
281 vp->v_freef = NULL;
282 vp->v_freeb = NULL;
283 VREF(vp);
284}
285
286/*
287 * Vnode reference, just increment the count
288 */
289void vref(vp)
290 struct vnode *vp;
291{
292
293 vp->v_count++;
294}
295
296/*
297 * vput(), just unlock and vrele()
298 */
299void vput(vp)
300 register struct vnode *vp;
301{
302 VOP_UNLOCK(vp);
303 vrele(vp);
304}
305
306/*
307 * Vnode release.
308 * If count drops to zero, call inactive routine and return to freelist.
309 */
310void vrele(vp)
311 register struct vnode *vp;
312{
313
314 if (vp == NULL)
315 return;
316 vp->v_count--;
317 if (vp->v_count < 0)
318 printf("vnode bad ref count %d, type %d, tag %d\n",
319 vp->v_count, vp->v_type, vp->v_tag);
320 if (vp->v_count > 0)
321 return;
322 VOP_INACTIVE(vp);
323 if (vfreeh == (struct vnode *)0) {
324 /*
325 * insert into empty list
326 */
327 vfreeh = vp;
328 vp->v_freeb = &vfreeh;
329 vp->v_freef = NULL;
330 vfreet = &vp->v_freef;
331 } else if (vp->v_type == VNON) {
332 /*
333 * insert at head of list
334 */
335 vp->v_freef = vfreeh;
336 vp->v_freeb = &vfreeh;
337 vfreeh->v_freeb = &vp->v_freef;
338 vfreeh = vp;
339 } else {
340 /*
341 * insert at tail of list
342 */
343 *vfreet = vp;
344 vp->v_freeb = vfreet;
345 vp->v_freef = NULL;
346 vfreet = &vp->v_freef;
347 }
348}