syslog portability for HP-UX; fix typo for OSF/1 pid file
[unix-history] / usr / src / sys / kern / vfs_subr.c
CommitLineData
3c4390e8 1/*
ec54f0cc
KB
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
3c4390e8 4 *
dbf0c423 5 * %sccs.include.redist.c%
3c4390e8 6 *
3fc2ac18 7 * @(#)vfs_subr.c 8.2 (Berkeley) %G%
3c4390e8
KM
8 */
9
10/*
11 * External virtual filesystem routines
12 */
13
cb796a23 14#include <sys/param.h>
917dc539 15#include <sys/systm.h>
cb796a23
KB
16#include <sys/proc.h>
17#include <sys/mount.h>
18#include <sys/time.h>
19#include <sys/vnode.h>
807cc430 20#include <sys/stat.h>
cb796a23
KB
21#include <sys/namei.h>
22#include <sys/ucred.h>
23#include <sys/buf.h>
24#include <sys/errno.h>
25#include <sys/malloc.h>
3c4390e8 26
bb4964fd
KM
27#include <vm/vm.h>
28#include <sys/sysctl.h>
29
021de758
JSP
30#include <miscfs/specfs/specdev.h>
31
807cc430
KM
32enum vtype iftovt_tab[16] = {
33 VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
34 VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD,
35};
36int vttoif_tab[9] = {
37 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK,
38 S_IFSOCK, S_IFIFO, S_IFMT,
39};
40
e3249ec0
KM
41/*
42 * Insq/Remq for the vnode usage lists.
43 */
3fc2ac18
KM
44#define NOLIST ((struct buf *)0x87654321)
45#define bufinsvn(bp, dp) LIST_INSERT_HEAD(dp, bp, b_vnbufs)
46#define bufremvn(bp) { \
47 LIST_REMOVE(bp, b_vnbufs); \
48 (bp)->b_vnbufs.le_next = NOLIST; \
49}
50
51TAILQ_HEAD(freelst, vnode) vnode_free_list; /* vnode free list */
52struct mntlist mountlist; /* mounted filesystem list */
e3249ec0 53
3c4390e8 54/*
3fc2ac18 55 * Initialize the vnode management data structures.
3c4390e8 56 */
3fc2ac18 57vntblinit()
3c4390e8
KM
58{
59
3fc2ac18
KM
60 TAILQ_INIT(&vnode_free_list);
61 TAILQ_INIT(&mountlist);
3c4390e8
KM
62}
63
64/*
65 * Lock a filesystem.
66 * Used to prevent access to it while mounting and unmounting.
67 */
68vfs_lock(mp)
69 register struct mount *mp;
70{
71
54fb9dc2
KM
72 while(mp->mnt_flag & MNT_MLOCK) {
73 mp->mnt_flag |= MNT_MWAIT;
594501df
KM
74 sleep((caddr_t)mp, PVFS);
75 }
54fb9dc2 76 mp->mnt_flag |= MNT_MLOCK;
3c4390e8
KM
77 return (0);
78}
79
80/*
81 * Unlock a locked filesystem.
82 * Panic if filesystem is not locked.
83 */
84void
85vfs_unlock(mp)
86 register struct mount *mp;
87{
88
54fb9dc2 89 if ((mp->mnt_flag & MNT_MLOCK) == 0)
36ef03ec 90 panic("vfs_unlock: not locked");
54fb9dc2
KM
91 mp->mnt_flag &= ~MNT_MLOCK;
92 if (mp->mnt_flag & MNT_MWAIT) {
93 mp->mnt_flag &= ~MNT_MWAIT;
3c4390e8
KM
94 wakeup((caddr_t)mp);
95 }
96}
97
36ef03ec
KM
98/*
99 * Mark a mount point as busy.
100 * Used to synchronize access and to delay unmounting.
101 */
102vfs_busy(mp)
103 register struct mount *mp;
104{
105
54fb9dc2
KM
106 while(mp->mnt_flag & MNT_MPBUSY) {
107 mp->mnt_flag |= MNT_MPWANT;
108 sleep((caddr_t)&mp->mnt_flag, PVFS);
36ef03ec 109 }
d8b63609
KM
110 if (mp->mnt_flag & MNT_UNMOUNT)
111 return (1);
54fb9dc2 112 mp->mnt_flag |= MNT_MPBUSY;
36ef03ec
KM
113 return (0);
114}
115
116/*
117 * Free a busy filesystem.
118 * Panic if filesystem is not busy.
119 */
36ef03ec
KM
120vfs_unbusy(mp)
121 register struct mount *mp;
122{
123
54fb9dc2 124 if ((mp->mnt_flag & MNT_MPBUSY) == 0)
36ef03ec 125 panic("vfs_unbusy: not busy");
54fb9dc2
KM
126 mp->mnt_flag &= ~MNT_MPBUSY;
127 if (mp->mnt_flag & MNT_MPWANT) {
128 mp->mnt_flag &= ~MNT_MPWANT;
129 wakeup((caddr_t)&mp->mnt_flag);
36ef03ec
KM
130 }
131}
132
3c4390e8
KM
133/*
134 * Lookup a mount point by filesystem identifier.
135 */
136struct mount *
137getvfs(fsid)
138 fsid_t *fsid;
139{
140 register struct mount *mp;
141
3fc2ac18 142 for (mp = mountlist.tqh_first; mp != NULL; mp = mp->mnt_list.tqe_next) {
54fb9dc2 143 if (mp->mnt_stat.f_fsid.val[0] == fsid->val[0] &&
3fc2ac18 144 mp->mnt_stat.f_fsid.val[1] == fsid->val[1])
d713f801 145 return (mp);
3fc2ac18 146 }
d713f801 147 return ((struct mount *)0);
3c4390e8
KM
148}
149
917dc539
JSP
150/*
151 * Get a new unique fsid
152 */
153void
154getnewfsid(mp, mtype)
155 struct mount *mp;
156 int mtype;
157{
158static u_short xxxfs_mntid;
159
160 fsid_t tfsid;
161
162 mp->mnt_stat.f_fsid.val[0] = makedev(nblkdev + 11, 0); /* XXX */
163 mp->mnt_stat.f_fsid.val[1] = mtype;
164 if (xxxfs_mntid == 0)
165 ++xxxfs_mntid;
166 tfsid.val[0] = makedev(nblkdev, xxxfs_mntid);
167 tfsid.val[1] = mtype;
3fc2ac18 168 if (mountlist.tqh_first != NULL) {
17fd1cc7
JSP
169 while (getvfs(&tfsid)) {
170 tfsid.val[0]++;
171 xxxfs_mntid++;
172 }
917dc539
JSP
173 }
174 mp->mnt_stat.f_fsid.val[0] = tfsid.val[0];
175}
176
3c4390e8
KM
177/*
178 * Set vnode attributes to VNOVAL
179 */
180void vattr_null(vap)
181 register struct vattr *vap;
182{
183
184 vap->va_type = VNON;
83504fd5 185 vap->va_size = vap->va_bytes = VNOVAL;
3c4390e8 186 vap->va_mode = vap->va_nlink = vap->va_uid = vap->va_gid =
83504fd5
KM
187 vap->va_fsid = vap->va_fileid =
188 vap->va_blocksize = vap->va_rdev =
ecf75a7d
KM
189 vap->va_atime.ts_sec = vap->va_atime.ts_nsec =
190 vap->va_mtime.ts_sec = vap->va_mtime.ts_nsec =
191 vap->va_ctime.ts_sec = vap->va_ctime.ts_nsec =
8cf4d4fb 192 vap->va_flags = vap->va_gen = VNOVAL;
fcba749b 193 vap->va_vaflags = 0;
3c4390e8 194}
c60798ca 195
36d09cb1
KM
196/*
197 * Routines having to do with the management of the vnode table.
198 */
9342689a 199extern int (**dead_vnodeop_p)();
32339c94 200extern void vclean();
1a80f56e 201long numvnodes;
e781da98 202extern struct vattr va_null;
36d09cb1
KM
203
204/*
205 * Return the next vnode from the free list.
206 */
207getnewvnode(tag, mp, vops, vpp)
208 enum vtagtype tag;
209 struct mount *mp;
cf74dd57 210 int (**vops)();
36d09cb1
KM
211 struct vnode **vpp;
212{
213 register struct vnode *vp, *vq;
1f9d2249 214 int s;
36d09cb1 215
3fc2ac18
KM
216 if ((vnode_free_list.tqh_first == NULL &&
217 numvnodes < 2 * desiredvnodes) ||
ecf75a7d 218 numvnodes < desiredvnodes) {
aacc1bff
KM
219 vp = (struct vnode *)malloc((u_long)sizeof *vp,
220 M_VNODE, M_WAITOK);
1a80f56e 221 bzero((char *)vp, sizeof *vp);
3fc2ac18 222 vp->v_usecount = 1;
1a80f56e
KM
223 numvnodes++;
224 } else {
3fc2ac18 225 if ((vp = vnode_free_list.tqh_first) == NULL) {
1a80f56e
KM
226 tablefull("vnode");
227 *vpp = 0;
228 return (ENFILE);
229 }
230 if (vp->v_usecount)
231 panic("free vnode isn't");
3fc2ac18
KM
232 TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
233 vp->v_usecount = 1;
39b99eb6 234 vp->v_lease = NULL;
1a80f56e
KM
235 if (vp->v_type != VBAD)
236 vgone(vp);
1f9d2249 237#ifdef DIAGNOSTIC
2345b093
KM
238 if (vp->v_data)
239 panic("cleaned vnode isn't");
1f9d2249
MS
240 s = splbio();
241 if (vp->v_numoutput)
242 panic("Clean vnode has pending I/O's");
243 splx(s);
244#endif
1a80f56e 245 vp->v_flag = 0;
1a80f56e 246 vp->v_lastr = 0;
1f9d2249
MS
247 vp->v_lastw = 0;
248 vp->v_lasta = 0;
249 vp->v_cstart = 0;
250 vp->v_clen = 0;
1a80f56e 251 vp->v_socket = 0;
36d09cb1 252 }
1f9d2249 253 vp->v_ralen = 1;
b027498b 254 vp->v_type = VNON;
36d09cb1
KM
255 cache_purge(vp);
256 vp->v_tag = tag;
ef24f6dd 257 vp->v_op = vops;
36d09cb1 258 insmntque(vp, mp);
36d09cb1 259 *vpp = vp;
3fc2ac18 260 vp->v_data = 0;
36d09cb1
KM
261 return (0);
262}
36d09cb1
KM
263/*
264 * Move a vnode from one mount queue to another.
265 */
266insmntque(vp, mp)
267 register struct vnode *vp;
268 register struct mount *mp;
269{
8136adfc 270 register struct vnode *vq;
36d09cb1
KM
271
272 /*
273 * Delete from old mount point vnode list, if on one.
274 */
3fc2ac18
KM
275 if (vp->v_mount != NULL)
276 LIST_REMOVE(vp, v_mntvnodes);
36d09cb1
KM
277 /*
278 * Insert into list of vnodes for the new mount point, if available.
279 */
3fc2ac18 280 if ((vp->v_mount = mp) == NULL)
36d09cb1 281 return;
3fc2ac18 282 LIST_INSERT_HEAD(&mp->mnt_vnodelist, vp, v_mntvnodes);
36d09cb1
KM
283}
284
76429560
KM
285/*
286 * Update outstanding I/O count and do wakeup if requested.
287 */
288vwakeup(bp)
289 register struct buf *bp;
290{
291 register struct vnode *vp;
292
a9338fad 293 bp->b_flags &= ~B_WRITEINPROG;
76429560
KM
294 if (vp = bp->b_vp) {
295 vp->v_numoutput--;
1f9d2249
MS
296 if (vp->v_numoutput < 0)
297 panic("vwakeup: neg numoutput");
76429560
KM
298 if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) {
299 if (vp->v_numoutput < 0)
300 panic("vwakeup: neg numoutput");
301 vp->v_flag &= ~VBWAIT;
302 wakeup((caddr_t)&vp->v_numoutput);
303 }
304 }
305}
306
76429560
KM
307/*
308 * Flush out and invalidate all buffers associated with a vnode.
309 * Called with the underlying object locked.
310 */
d024c2ce 311int
c33e9e8b 312vinvalbuf(vp, flags, cred, p, slpflag, slptimeo)
76429560 313 register struct vnode *vp;
12079a9d 314 int flags;
d024c2ce
KM
315 struct ucred *cred;
316 struct proc *p;
c33e9e8b 317 int slpflag, slptimeo;
76429560
KM
318{
319 register struct buf *bp;
320 struct buf *nbp, *blist;
d024c2ce 321 int s, error;
76429560 322
12079a9d 323 if (flags & V_SAVE) {
d024c2ce
KM
324 if (error = VOP_FSYNC(vp, cred, MNT_WAIT, p))
325 return (error);
3fc2ac18 326 if (vp->v_dirtyblkhd.lh_first != NULL)
d024c2ce
KM
327 panic("vinvalbuf: dirty bufs");
328 }
76429560 329 for (;;) {
3fc2ac18 330 if ((blist = vp->v_cleanblkhd.lh_first) && flags & V_SAVEMETA)
12079a9d 331 while (blist && blist->b_lblkno < 0)
3fc2ac18
KM
332 blist = blist->b_vnbufs.le_next;
333 if (!blist && (blist = vp->v_dirtyblkhd.lh_first) &&
e3249ec0 334 (flags & V_SAVEMETA))
12079a9d 335 while (blist && blist->b_lblkno < 0)
3fc2ac18 336 blist = blist->b_vnbufs.le_next;
12079a9d 337 if (!blist)
76429560 338 break;
12079a9d 339
76429560 340 for (bp = blist; bp; bp = nbp) {
3fc2ac18 341 nbp = bp->b_vnbufs.le_next;
12079a9d
MS
342 if (flags & V_SAVEMETA && bp->b_lblkno < 0)
343 continue;
76429560
KM
344 s = splbio();
345 if (bp->b_flags & B_BUSY) {
346 bp->b_flags |= B_WANTED;
c33e9e8b
KM
347 error = tsleep((caddr_t)bp,
348 slpflag | (PRIBIO + 1), "vinvalbuf",
349 slptimeo);
76429560 350 splx(s);
c33e9e8b
KM
351 if (error)
352 return (error);
76429560
KM
353 break;
354 }
355 bremfree(bp);
356 bp->b_flags |= B_BUSY;
357 splx(s);
c33e9e8b
KM
358 /*
359 * XXX Since there are no node locks for NFS, I believe
360 * there is a slight chance that a delayed write will
361 * occur while sleeping just above, so check for it.
362 */
363 if ((bp->b_flags & B_DELWRI) && (flags & V_SAVE)) {
364 (void) VOP_BWRITE(bp);
365 break;
366 }
12079a9d 367 bp->b_flags |= B_INVAL;
76429560
KM
368 brelse(bp);
369 }
370 }
e3249ec0 371 if (!(flags & V_SAVEMETA) &&
3fc2ac18 372 (vp->v_dirtyblkhd.lh_first || vp->v_cleanblkhd.lh_first))
76429560 373 panic("vinvalbuf: flush failed");
d024c2ce 374 return (0);
76429560
KM
375}
376
377/*
378 * Associate a buffer with a vnode.
379 */
380bgetvp(vp, bp)
381 register struct vnode *vp;
382 register struct buf *bp;
383{
8136adfc 384 register struct vnode *vq;
76429560
KM
385
386 if (bp->b_vp)
387 panic("bgetvp: not free");
388 VHOLD(vp);
389 bp->b_vp = vp;
390 if (vp->v_type == VBLK || vp->v_type == VCHR)
391 bp->b_dev = vp->v_rdev;
392 else
393 bp->b_dev = NODEV;
394 /*
395 * Insert onto list for new vnode.
396 */
e3249ec0 397 bufinsvn(bp, &vp->v_cleanblkhd);
76429560
KM
398}
399
400/*
401 * Disassociate a buffer from a vnode.
402 */
403brelvp(bp)
404 register struct buf *bp;
405{
76429560
KM
406 struct vnode *vp;
407
408 if (bp->b_vp == (struct vnode *) 0)
409 panic("brelvp: NULL");
410 /*
411 * Delete from old vnode list, if on one.
412 */
3fc2ac18 413 if (bp->b_vnbufs.le_next != NOLIST)
e3249ec0 414 bufremvn(bp);
76429560
KM
415 vp = bp->b_vp;
416 bp->b_vp = (struct vnode *) 0;
417 HOLDRELE(vp);
418}
419
420/*
421 * Reassign a buffer from one vnode to another.
422 * Used to assign file specific control information
423 * (indirect blocks) to the vnode to which they belong.
424 */
425reassignbuf(bp, newvp)
426 register struct buf *bp;
427 register struct vnode *newvp;
428{
3fc2ac18 429 register struct buflists *listheadp;
76429560 430
e5c3f16e
KM
431 if (newvp == NULL) {
432 printf("reassignbuf: NULL");
433 return;
434 }
76429560
KM
435 /*
436 * Delete from old vnode list, if on one.
437 */
3fc2ac18 438 if (bp->b_vnbufs.le_next != NOLIST)
e3249ec0 439 bufremvn(bp);
76429560
KM
440 /*
441 * If dirty, put on list of dirty buffers;
442 * otherwise insert onto list of clean buffers.
443 */
444 if (bp->b_flags & B_DELWRI)
445 listheadp = &newvp->v_dirtyblkhd;
446 else
447 listheadp = &newvp->v_cleanblkhd;
e3249ec0 448 bufinsvn(bp, listheadp);
76429560
KM
449}
450
36d09cb1 451/*
ef24f6dd
KM
452 * Create a vnode for a block device.
453 * Used for root filesystem, argdev, and swap areas.
454 * Also used for memory file system special devices.
455 */
456bdevvp(dev, vpp)
457 dev_t dev;
458 struct vnode **vpp;
459{
ef24f6dd
KM
460 register struct vnode *vp;
461 struct vnode *nvp;
462 int error;
463
1c89915d
KM
464 if (dev == NODEV)
465 return (0);
9342689a 466 error = getnewvnode(VT_NON, (struct mount *)0, spec_vnodeop_p, &nvp);
ef24f6dd
KM
467 if (error) {
468 *vpp = 0;
469 return (error);
470 }
471 vp = nvp;
472 vp->v_type = VBLK;
c0de8792 473 if (nvp = checkalias(vp, dev, (struct mount *)0)) {
ef24f6dd
KM
474 vput(vp);
475 vp = nvp;
476 }
477 *vpp = vp;
478 return (0);
479}
480
481/*
482 * Check to see if the new vnode represents a special device
483 * for which we already have a vnode (either because of
484 * bdevvp() or because of a different vnode representing
485 * the same block device). If such an alias exists, deallocate
f0556f86 486 * the existing contents and return the aliased vnode. The
ef24f6dd
KM
487 * caller is responsible for filling it with its new contents.
488 */
489struct vnode *
c0de8792 490checkalias(nvp, nvp_rdev, mp)
ef24f6dd 491 register struct vnode *nvp;
c0de8792 492 dev_t nvp_rdev;
ef24f6dd
KM
493 struct mount *mp;
494{
495 register struct vnode *vp;
c0de8792 496 struct vnode **vpp;
ef24f6dd
KM
497
498 if (nvp->v_type != VBLK && nvp->v_type != VCHR)
54fb9dc2 499 return (NULLVP);
c0de8792
KM
500
501 vpp = &speclisth[SPECHASH(nvp_rdev)];
ef24f6dd 502loop:
c0de8792
KM
503 for (vp = *vpp; vp; vp = vp->v_specnext) {
504 if (nvp_rdev != vp->v_rdev || nvp->v_type != vp->v_type)
ef24f6dd 505 continue;
c0de8792
KM
506 /*
507 * Alias, but not in use, so flush it out.
508 */
7f7b7d89 509 if (vp->v_usecount == 0) {
c0de8792
KM
510 vgone(vp);
511 goto loop;
512 }
3fc2ac18 513 if (vget(vp, 1))
ef62830d 514 goto loop;
ef24f6dd
KM
515 break;
516 }
c0de8792 517 if (vp == NULL || vp->v_tag != VT_NON) {
c0de8792
KM
518 MALLOC(nvp->v_specinfo, struct specinfo *,
519 sizeof(struct specinfo), M_VNODE, M_WAITOK);
520 nvp->v_rdev = nvp_rdev;
7f7b7d89 521 nvp->v_hashchain = vpp;
c0de8792 522 nvp->v_specnext = *vpp;
2c957a90 523 nvp->v_specflags = 0;
c0de8792 524 *vpp = nvp;
40452d5e
KM
525 if (vp != NULL) {
526 nvp->v_flag |= VALIASED;
527 vp->v_flag |= VALIASED;
528 vput(vp);
529 }
54fb9dc2 530 return (NULLVP);
ef24f6dd 531 }
2bae1875
KM
532 VOP_UNLOCK(vp);
533 vclean(vp, 0);
ef24f6dd
KM
534 vp->v_op = nvp->v_op;
535 vp->v_tag = nvp->v_tag;
536 nvp->v_type = VNON;
537 insmntque(vp, mp);
538 return (vp);
539}
540
541/*
542 * Grab a particular vnode from the free list, increment its
543 * reference count and lock it. The vnode lock bit is set the
544 * vnode is being eliminated in vgone. The process is awakened
545 * when the transition is completed, and an error returned to
546 * indicate that the vnode is no longer usable (possibly having
547 * been changed to a new file system type).
36d09cb1 548 */
3fc2ac18 549vget(vp, lockflag)
36d09cb1 550 register struct vnode *vp;
3fc2ac18 551 int lockflag;
36d09cb1
KM
552{
553 register struct vnode *vq;
554
ef24f6dd
KM
555 if (vp->v_flag & VXLOCK) {
556 vp->v_flag |= VXWANT;
557 sleep((caddr_t)vp, PINOD);
558 return (1);
559 }
3fc2ac18
KM
560 if (vp->v_usecount == 0)
561 TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
ec04fc59 562 vp->v_usecount++;
3fc2ac18
KM
563 if (lockflag)
564 VOP_LOCK(vp);
ef24f6dd 565 return (0);
36d09cb1
KM
566}
567
d32390ea
KM
568int bug_refs = 0;
569
36d09cb1
KM
570/*
571 * Vnode reference, just increment the count
572 */
573void vref(vp)
574 struct vnode *vp;
575{
576
ec04fc59
KM
577 if (vp->v_usecount <= 0)
578 panic("vref used where vget required");
7f7b7d89 579 vp->v_usecount++;
d32390ea
KM
580 if (vp->v_type != VBLK && curproc)
581 curproc->p_spare[0]++;
582 if (bug_refs)
583 vprint("vref: ");
36d09cb1
KM
584}
585
586/*
587 * vput(), just unlock and vrele()
588 */
589void vput(vp)
590 register struct vnode *vp;
591{
4d1ee2eb 592
36d09cb1
KM
593 VOP_UNLOCK(vp);
594 vrele(vp);
595}
596
597/*
598 * Vnode release.
599 * If count drops to zero, call inactive routine and return to freelist.
600 */
601void vrele(vp)
602 register struct vnode *vp;
603{
604
65c3b3a8 605#ifdef DIAGNOSTIC
36d09cb1 606 if (vp == NULL)
ef24f6dd 607 panic("vrele: null vp");
65c3b3a8 608#endif
7f7b7d89 609 vp->v_usecount--;
d32390ea
KM
610 if (vp->v_type != VBLK && curproc)
611 curproc->p_spare[0]--;
612 if (bug_refs)
613 vprint("vref: ");
7f7b7d89 614 if (vp->v_usecount > 0)
36d09cb1 615 return;
65c3b3a8
KM
616#ifdef DIAGNOSTIC
617 if (vp->v_usecount != 0 || vp->v_writecount != 0) {
618 vprint("vrele: bad ref count", vp);
619 panic("vrele: ref cnt");
620 }
621#endif
dc998e72
KM
622 /*
623 * insert at tail of LRU list
624 */
3fc2ac18 625 TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
d024c2ce 626 VOP_INACTIVE(vp);
ef24f6dd
KM
627}
628
7f7b7d89
KM
629/*
630 * Page or buffer structure gets a reference.
631 */
451df175 632void vhold(vp)
7f7b7d89
KM
633 register struct vnode *vp;
634{
635
636 vp->v_holdcnt++;
637}
638
639/*
640 * Page or buffer structure frees a reference.
641 */
451df175 642void holdrele(vp)
7f7b7d89
KM
643 register struct vnode *vp;
644{
645
646 if (vp->v_holdcnt <= 0)
647 panic("holdrele: holdcnt");
648 vp->v_holdcnt--;
649}
650
f0556f86
KM
651/*
652 * Remove any vnodes in the vnode table belonging to mount point mp.
653 *
654 * If MNT_NOFORCE is specified, there should not be any active ones,
655 * return error if any are found (nb: this is a user error, not a
656 * system error). If MNT_FORCE is specified, detach any active vnodes
657 * that are found.
658 */
bb4964fd
KM
659int busyprt = 0; /* print out busy vnodes */
660struct ctldebug debug1 = { "busyprt", &busyprt };
f0556f86
KM
661
662vflush(mp, skipvp, flags)
663 struct mount *mp;
664 struct vnode *skipvp;
665 int flags;
666{
667 register struct vnode *vp, *nvp;
668 int busy = 0;
669
54fb9dc2 670 if ((mp->mnt_flag & MNT_MPBUSY) == 0)
36ef03ec 671 panic("vflush: not busy");
4597dd33 672loop:
3fc2ac18 673 for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) {
4597dd33
KM
674 if (vp->v_mount != mp)
675 goto loop;
3fc2ac18 676 nvp = vp->v_mntvnodes.le_next;
f0556f86
KM
677 /*
678 * Skip over a selected vnode.
f0556f86
KM
679 */
680 if (vp == skipvp)
681 continue;
36ef03ec
KM
682 /*
683 * Skip over a vnodes marked VSYSTEM.
684 */
685 if ((flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM))
686 continue;
da374605
KM
687 /*
688 * If WRITECLOSE is set, only flush out regular file
689 * vnodes open for writing.
690 */
691 if ((flags & WRITECLOSE) &&
692 (vp->v_writecount == 0 || vp->v_type != VREG))
693 continue;
f0556f86 694 /*
7f7b7d89 695 * With v_usecount == 0, all we need to do is clear
f0556f86
KM
696 * out the vnode data structures and we are done.
697 */
7f7b7d89 698 if (vp->v_usecount == 0) {
f0556f86
KM
699 vgone(vp);
700 continue;
701 }
702 /*
da374605 703 * If FORCECLOSE is set, forcibly close the vnode.
f0556f86
KM
704 * For block or character devices, revert to an
705 * anonymous device. For all other files, just kill them.
706 */
36ef03ec 707 if (flags & FORCECLOSE) {
f0556f86
KM
708 if (vp->v_type != VBLK && vp->v_type != VCHR) {
709 vgone(vp);
710 } else {
711 vclean(vp, 0);
9342689a 712 vp->v_op = spec_vnodeop_p;
f0556f86
KM
713 insmntque(vp, (struct mount *)0);
714 }
715 continue;
716 }
717 if (busyprt)
0bf84b18 718 vprint("vflush: busy vnode", vp);
f0556f86
KM
719 busy++;
720 }
721 if (busy)
722 return (EBUSY);
723 return (0);
724}
725
ef24f6dd
KM
726/*
727 * Disassociate the underlying file system from a vnode.
ef24f6dd 728 */
ecf75a7d
KM
729void
730vclean(vp, flags)
ef24f6dd 731 register struct vnode *vp;
aacc1bff 732 int flags;
ef24f6dd 733{
2bae1875 734 int active;
ef24f6dd 735
2bae1875
KM
736 /*
737 * Check to see if the vnode is in use.
0bf84b18
KM
738 * If so we have to reference it before we clean it out
739 * so that its count cannot fall to zero and generate a
740 * race against ourselves to recycle it.
2bae1875 741 */
7f7b7d89 742 if (active = vp->v_usecount)
2bae1875 743 VREF(vp);
669df1aa
KM
744 /*
745 * Even if the count is zero, the VOP_INACTIVE routine may still
746 * have the object locked while it cleans it out. The VOP_LOCK
747 * ensures that the VOP_INACTIVE routine is done with its work.
748 * For active vnodes, it ensures that no other activity can
749 * occur while the underlying object is being cleaned out.
750 */
751 VOP_LOCK(vp);
2bae1875
KM
752 /*
753 * Prevent the vnode from being recycled or
754 * brought into use while we clean it out.
755 */
0bf84b18
KM
756 if (vp->v_flag & VXLOCK)
757 panic("vclean: deadlock");
ef24f6dd 758 vp->v_flag |= VXLOCK;
0bf84b18 759 /*
669df1aa 760 * Clean out any buffers associated with the vnode.
0bf84b18 761 */
36ef03ec 762 if (flags & DOCLOSE)
c33e9e8b 763 vinvalbuf(vp, V_SAVE, NOCRED, NULL, 0, 0);
ef24f6dd 764 /*
669df1aa
KM
765 * Any other processes trying to obtain this lock must first
766 * wait for VXLOCK to clear, then call the new lock operation.
ef24f6dd 767 */
669df1aa 768 VOP_UNLOCK(vp);
ef24f6dd 769 /*
669df1aa
KM
770 * If purging an active vnode, it must be closed and
771 * deactivated before being reclaimed.
ef24f6dd 772 */
2bae1875 773 if (active) {
669df1aa
KM
774 if (flags & DOCLOSE)
775 VOP_CLOSE(vp, IO_NDELAY, NOCRED, NULL);
776 VOP_INACTIVE(vp);
ef24f6dd
KM
777 }
778 /*
779 * Reclaim the vnode.
780 */
669df1aa 781 if (VOP_RECLAIM(vp))
ef24f6dd 782 panic("vclean: cannot reclaim");
2bae1875
KM
783 if (active)
784 vrele(vp);
38c46eee 785
ef24f6dd 786 /*
669df1aa 787 * Done with purge, notify sleepers of the grim news.
ef24f6dd 788 */
669df1aa
KM
789 vp->v_op = dead_vnodeop_p;
790 vp->v_tag = VT_NON;
ef24f6dd
KM
791 vp->v_flag &= ~VXLOCK;
792 if (vp->v_flag & VXWANT) {
793 vp->v_flag &= ~VXWANT;
794 wakeup((caddr_t)vp);
795 }
796}
797
ef62830d
KM
798/*
799 * Eliminate all activity associated with the requested vnode
800 * and with all vnodes aliased to the requested vnode.
801 */
802void vgoneall(vp)
803 register struct vnode *vp;
804{
7f7b7d89 805 register struct vnode *vq;
ef62830d 806
7a7b3a95
KM
807 if (vp->v_flag & VALIASED) {
808 /*
809 * If a vgone (or vclean) is already in progress,
810 * wait until it is done and return.
811 */
812 if (vp->v_flag & VXLOCK) {
813 vp->v_flag |= VXWANT;
814 sleep((caddr_t)vp, PINOD);
815 return;
816 }
817 /*
818 * Ensure that vp will not be vgone'd while we
819 * are eliminating its aliases.
820 */
821 vp->v_flag |= VXLOCK;
822 while (vp->v_flag & VALIASED) {
823 for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
824 if (vq->v_rdev != vp->v_rdev ||
825 vq->v_type != vp->v_type || vp == vq)
826 continue;
827 vgone(vq);
828 break;
829 }
ef62830d 830 }
7a7b3a95
KM
831 /*
832 * Remove the lock so that vgone below will
833 * really eliminate the vnode after which time
834 * vgone will awaken any sleepers.
835 */
836 vp->v_flag &= ~VXLOCK;
ef62830d
KM
837 }
838 vgone(vp);
839}
840
ef24f6dd
KM
841/*
842 * Eliminate all activity associated with a vnode
843 * in preparation for reuse.
844 */
845void vgone(vp)
846 register struct vnode *vp;
847{
7f7b7d89 848 register struct vnode *vq;
c0de8792 849 struct vnode *vx;
ef24f6dd 850
4f55e3ec
KM
851 /*
852 * If a vgone (or vclean) is already in progress,
853 * wait until it is done and return.
854 */
855 if (vp->v_flag & VXLOCK) {
856 vp->v_flag |= VXWANT;
857 sleep((caddr_t)vp, PINOD);
858 return;
859 }
ef24f6dd
KM
860 /*
861 * Clean out the filesystem specific data.
862 */
36ef03ec 863 vclean(vp, DOCLOSE);
ef24f6dd
KM
864 /*
865 * Delete from old mount point vnode list, if on one.
866 */
3fc2ac18
KM
867 if (vp->v_mount != NULL) {
868 LIST_REMOVE(vp, v_mntvnodes);
d10e9258 869 vp->v_mount = NULL;
ef24f6dd
KM
870 }
871 /*
872 * If special device, remove it from special device alias list.
873 */
874 if (vp->v_type == VBLK || vp->v_type == VCHR) {
7f7b7d89
KM
875 if (*vp->v_hashchain == vp) {
876 *vp->v_hashchain = vp->v_specnext;
ef24f6dd 877 } else {
7f7b7d89 878 for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
c0de8792 879 if (vq->v_specnext != vp)
ef24f6dd 880 continue;
c0de8792 881 vq->v_specnext = vp->v_specnext;
ef24f6dd
KM
882 break;
883 }
c0de8792 884 if (vq == NULL)
ef24f6dd
KM
885 panic("missing bdev");
886 }
c0de8792 887 if (vp->v_flag & VALIASED) {
4d1ee2eb 888 vx = NULL;
7f7b7d89 889 for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
de81e10c
KM
890 if (vq->v_rdev != vp->v_rdev ||
891 vq->v_type != vp->v_type)
c0de8792 892 continue;
4d1ee2eb
CT
893 if (vx)
894 break;
c0de8792
KM
895 vx = vq;
896 }
4d1ee2eb 897 if (vx == NULL)
c0de8792 898 panic("missing alias");
4d1ee2eb 899 if (vq == NULL)
c0de8792
KM
900 vx->v_flag &= ~VALIASED;
901 vp->v_flag &= ~VALIASED;
902 }
903 FREE(vp->v_specinfo, M_VNODE);
904 vp->v_specinfo = NULL;
ef24f6dd
KM
905 }
906 /*
3387ef89
KM
907 * If it is on the freelist and not already at the head,
908 * move it to the head of the list.
ef24f6dd 909 */
3fc2ac18
KM
910 if (vp->v_usecount == 0 && vnode_free_list.tqh_first != vp) {
911 TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
912 TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
ef24f6dd 913 }
2bae1875 914 vp->v_type = VBAD;
36d09cb1 915}
ef62830d 916
2bcd6066
KM
917/*
918 * Lookup a vnode by device number.
919 */
920vfinddev(dev, type, vpp)
921 dev_t dev;
922 enum vtype type;
923 struct vnode **vpp;
924{
925 register struct vnode *vp;
926
927 for (vp = speclisth[SPECHASH(dev)]; vp; vp = vp->v_specnext) {
928 if (dev != vp->v_rdev || type != vp->v_type)
929 continue;
930 *vpp = vp;
05378ee4 931 return (1);
2bcd6066 932 }
05378ee4 933 return (0);
2bcd6066
KM
934}
935
ef62830d
KM
936/*
937 * Calculate the total number of references to a special device.
938 */
939vcount(vp)
940 register struct vnode *vp;
941{
7f7b7d89 942 register struct vnode *vq;
ef62830d
KM
943 int count;
944
945 if ((vp->v_flag & VALIASED) == 0)
7f7b7d89 946 return (vp->v_usecount);
ef62830d 947loop:
7f7b7d89 948 for (count = 0, vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
de81e10c 949 if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type)
ef62830d
KM
950 continue;
951 /*
952 * Alias, but not in use, so flush it out.
953 */
7f7b7d89 954 if (vq->v_usecount == 0) {
ef62830d
KM
955 vgone(vq);
956 goto loop;
957 }
7f7b7d89 958 count += vq->v_usecount;
ef62830d
KM
959 }
960 return (count);
961}
0bf84b18
KM
962
963/*
964 * Print out a description of a vnode.
965 */
966static char *typename[] =
61f846a8 967 { "VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD" };
0bf84b18
KM
968
969vprint(label, vp)
970 char *label;
971 register struct vnode *vp;
972{
f2f730c6 973 char buf[64];
0bf84b18
KM
974
975 if (label != NULL)
976 printf("%s: ", label);
65c3b3a8
KM
977 printf("type %s, usecount %d, writecount %d, refcount %d,",
978 typename[vp->v_type], vp->v_usecount, vp->v_writecount,
979 vp->v_holdcnt);
f2f730c6
KM
980 buf[0] = '\0';
981 if (vp->v_flag & VROOT)
982 strcat(buf, "|VROOT");
983 if (vp->v_flag & VTEXT)
984 strcat(buf, "|VTEXT");
36ef03ec
KM
985 if (vp->v_flag & VSYSTEM)
986 strcat(buf, "|VSYSTEM");
36ef03ec
KM
987 if (vp->v_flag & VXLOCK)
988 strcat(buf, "|VXLOCK");
989 if (vp->v_flag & VXWANT)
990 strcat(buf, "|VXWANT");
f2f730c6
KM
991 if (vp->v_flag & VBWAIT)
992 strcat(buf, "|VBWAIT");
36ef03ec
KM
993 if (vp->v_flag & VALIASED)
994 strcat(buf, "|VALIASED");
f2f730c6
KM
995 if (buf[0] != '\0')
996 printf(" flags (%s)", &buf[1]);
3fc2ac18
KM
997 if (vp->v_data == NULL) {
998 printf("\n");
999 } else {
1000 printf("\n\t");
1001 VOP_PRINT(vp);
1002 }
0bf84b18 1003}
985cbdd5 1004
34c62e18
KM
1005#ifdef DEBUG
1006/*
1007 * List all of the locked vnodes in the system.
1008 * Called when debugging the kernel.
1009 */
1010printlockedvnodes()
1011{
1012 register struct mount *mp;
1013 register struct vnode *vp;
1014
1015 printf("Locked vnodes\n");
3fc2ac18
KM
1016 for (mp = mountlist.tqh_first; mp != NULL; mp = mp->mnt_list.tqe_next) {
1017 for (vp = mp->mnt_vnodelist.lh_first;
1018 vp != NULL;
1019 vp = vp->v_mntvnodes.le_next)
34c62e18
KM
1020 if (VOP_ISLOCKED(vp))
1021 vprint((char *)0, vp);
3fc2ac18 1022 }
34c62e18
KM
1023}
1024#endif
1025
985cbdd5
MT
1026int kinfo_vdebug = 1;
1027int kinfo_vgetfailed;
1028#define KINFO_VNODESLOP 10
1029/*
786fb484 1030 * Dump vnode list (via sysctl).
985cbdd5
MT
1031 * Copyout address of vnode followed by vnode.
1032 */
aacc1bff 1033/* ARGSUSED */
786fb484 1034sysctl_vnode(where, sizep)
985cbdd5 1035 char *where;
c1909da4 1036 size_t *sizep;
985cbdd5 1037{
3fc2ac18 1038 register struct mount *mp, *nmp;
985cbdd5 1039 struct vnode *vp;
985cbdd5 1040 register char *bp = where, *savebp;
5bf57294 1041 char *ewhere;
985cbdd5
MT
1042 int error;
1043
1044#define VPTRSZ sizeof (struct vnode *)
1045#define VNODESZ sizeof (struct vnode)
1046 if (where == NULL) {
786fb484 1047 *sizep = (numvnodes + KINFO_VNODESLOP) * (VPTRSZ + VNODESZ);
985cbdd5
MT
1048 return (0);
1049 }
786fb484 1050 ewhere = where + *sizep;
985cbdd5 1051
3fc2ac18
KM
1052 for (mp = mountlist.tqh_first; mp != NULL; mp = nmp) {
1053 nmp = mp->mnt_list.tqe_next;
1054 if (vfs_busy(mp))
36ef03ec 1055 continue;
985cbdd5
MT
1056 savebp = bp;
1057again:
3fc2ac18
KM
1058 for (vp = mp->mnt_vnodelist.lh_first;
1059 vp != NULL;
1060 vp = vp->v_mntvnodes.le_next) {
41185b3b
KM
1061 /*
1062 * Check that the vp is still associated with
1063 * this filesystem. RACE: could have been
1064 * recycled onto the same filesystem.
1065 */
4597dd33
KM
1066 if (vp->v_mount != mp) {
1067 if (kinfo_vdebug)
1068 printf("kinfo: vp changed\n");
1069 bp = savebp;
1070 goto again;
1071 }
786fb484
KM
1072 if (bp + VPTRSZ + VNODESZ > ewhere) {
1073 *sizep = bp - where;
1074 return (ENOMEM);
1075 }
1076 if ((error = copyout((caddr_t)&vp, bp, VPTRSZ)) ||
1077 (error = copyout((caddr_t)vp, bp + VPTRSZ, VNODESZ)))
985cbdd5 1078 return (error);
985cbdd5 1079 bp += VPTRSZ + VNODESZ;
985cbdd5 1080 }
3fc2ac18
KM
1081 vfs_unbusy(mp);
1082 }
985cbdd5 1083
786fb484 1084 *sizep = bp - where;
985cbdd5
MT
1085 return (0);
1086}