allow revoke on any file; vgoneall => VOP_REVOKE
[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.
adb35f79
KB
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
3c4390e8 9 *
dbf0c423 10 * %sccs.include.redist.c%
3c4390e8 11 *
05560902 12 * @(#)vfs_subr.c 8.15 (Berkeley) %G%
3c4390e8
KM
13 */
14
15/*
16 * External virtual filesystem routines
17 */
18
cb796a23 19#include <sys/param.h>
917dc539 20#include <sys/systm.h>
cb796a23
KB
21#include <sys/proc.h>
22#include <sys/mount.h>
23#include <sys/time.h>
24#include <sys/vnode.h>
807cc430 25#include <sys/stat.h>
cb796a23
KB
26#include <sys/namei.h>
27#include <sys/ucred.h>
28#include <sys/buf.h>
29#include <sys/errno.h>
30#include <sys/malloc.h>
8981e258
MH
31#include <sys/domain.h>
32#include <sys/mbuf.h>
3c4390e8 33
bb4964fd
KM
34#include <vm/vm.h>
35#include <sys/sysctl.h>
36
021de758
JSP
37#include <miscfs/specfs/specdev.h>
38
807cc430
KM
39enum vtype iftovt_tab[16] = {
40 VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
41 VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD,
42};
43int vttoif_tab[9] = {
44 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK,
45 S_IFSOCK, S_IFIFO, S_IFMT,
46};
47
e3249ec0
KM
48/*
49 * Insq/Remq for the vnode usage lists.
50 */
3fc2ac18 51#define bufinsvn(bp, dp) LIST_INSERT_HEAD(dp, bp, b_vnbufs)
05560902
CD
52#define bufremvn(bp) { \
53 LIST_REMOVE(bp, b_vnbufs); \
54 (bp)->b_vnbufs.le_next = NOLIST; \
3fc2ac18 55}
3fc2ac18
KM
56TAILQ_HEAD(freelst, vnode) vnode_free_list; /* vnode free list */
57struct mntlist mountlist; /* mounted filesystem list */
e3249ec0 58
3c4390e8 59/*
3fc2ac18 60 * Initialize the vnode management data structures.
3c4390e8 61 */
05560902 62void
3fc2ac18 63vntblinit()
3c4390e8
KM
64{
65
3fc2ac18
KM
66 TAILQ_INIT(&vnode_free_list);
67 TAILQ_INIT(&mountlist);
3c4390e8
KM
68}
69
70/*
71 * Lock a filesystem.
72 * Used to prevent access to it while mounting and unmounting.
73 */
05560902 74int
3c4390e8
KM
75vfs_lock(mp)
76 register struct mount *mp;
77{
78
05560902 79 while (mp->mnt_flag & MNT_MLOCK) {
54fb9dc2 80 mp->mnt_flag |= MNT_MWAIT;
05560902 81 tsleep((caddr_t)mp, PVFS, "vfslock", 0);
594501df 82 }
54fb9dc2 83 mp->mnt_flag |= MNT_MLOCK;
3c4390e8
KM
84 return (0);
85}
86
87/*
88 * Unlock a locked filesystem.
89 * Panic if filesystem is not locked.
90 */
91void
92vfs_unlock(mp)
93 register struct mount *mp;
94{
95
54fb9dc2 96 if ((mp->mnt_flag & MNT_MLOCK) == 0)
36ef03ec 97 panic("vfs_unlock: not locked");
54fb9dc2
KM
98 mp->mnt_flag &= ~MNT_MLOCK;
99 if (mp->mnt_flag & MNT_MWAIT) {
100 mp->mnt_flag &= ~MNT_MWAIT;
3c4390e8
KM
101 wakeup((caddr_t)mp);
102 }
103}
104
36ef03ec
KM
105/*
106 * Mark a mount point as busy.
107 * Used to synchronize access and to delay unmounting.
108 */
05560902 109int
36ef03ec
KM
110vfs_busy(mp)
111 register struct mount *mp;
112{
113
05560902 114 while (mp->mnt_flag & MNT_MPBUSY) {
54fb9dc2 115 mp->mnt_flag |= MNT_MPWANT;
05560902 116 tsleep((caddr_t)&mp->mnt_flag, PVFS, "vfsbusy", 0);
36ef03ec 117 }
d8b63609
KM
118 if (mp->mnt_flag & MNT_UNMOUNT)
119 return (1);
54fb9dc2 120 mp->mnt_flag |= MNT_MPBUSY;
36ef03ec
KM
121 return (0);
122}
123
124/*
125 * Free a busy filesystem.
126 * Panic if filesystem is not busy.
127 */
05560902 128void
36ef03ec
KM
129vfs_unbusy(mp)
130 register struct mount *mp;
131{
132
54fb9dc2 133 if ((mp->mnt_flag & MNT_MPBUSY) == 0)
36ef03ec 134 panic("vfs_unbusy: not busy");
54fb9dc2
KM
135 mp->mnt_flag &= ~MNT_MPBUSY;
136 if (mp->mnt_flag & MNT_MPWANT) {
137 mp->mnt_flag &= ~MNT_MPWANT;
138 wakeup((caddr_t)&mp->mnt_flag);
36ef03ec
KM
139 }
140}
141
3c4390e8
KM
142/*
143 * Lookup a mount point by filesystem identifier.
144 */
145struct mount *
146getvfs(fsid)
147 fsid_t *fsid;
148{
149 register struct mount *mp;
150
3fc2ac18 151 for (mp = mountlist.tqh_first; mp != NULL; mp = mp->mnt_list.tqe_next) {
54fb9dc2 152 if (mp->mnt_stat.f_fsid.val[0] == fsid->val[0] &&
3fc2ac18 153 mp->mnt_stat.f_fsid.val[1] == fsid->val[1])
d713f801 154 return (mp);
3fc2ac18 155 }
d713f801 156 return ((struct mount *)0);
3c4390e8
KM
157}
158
917dc539
JSP
159/*
160 * Get a new unique fsid
161 */
162void
163getnewfsid(mp, mtype)
164 struct mount *mp;
165 int mtype;
166{
167static u_short xxxfs_mntid;
168
169 fsid_t tfsid;
170
1209b9a4 171 mp->mnt_stat.f_fsid.val[0] = makedev(nblkdev + mtype, 0);
917dc539
JSP
172 mp->mnt_stat.f_fsid.val[1] = mtype;
173 if (xxxfs_mntid == 0)
174 ++xxxfs_mntid;
1209b9a4 175 tfsid.val[0] = makedev(nblkdev + mtype, xxxfs_mntid);
917dc539 176 tfsid.val[1] = mtype;
3fc2ac18 177 if (mountlist.tqh_first != NULL) {
17fd1cc7
JSP
178 while (getvfs(&tfsid)) {
179 tfsid.val[0]++;
180 xxxfs_mntid++;
181 }
917dc539
JSP
182 }
183 mp->mnt_stat.f_fsid.val[0] = tfsid.val[0];
184}
185
3c4390e8
KM
186/*
187 * Set vnode attributes to VNOVAL
188 */
05560902
CD
189void
190vattr_null(vap)
3c4390e8
KM
191 register struct vattr *vap;
192{
193
194 vap->va_type = VNON;
83504fd5 195 vap->va_size = vap->va_bytes = VNOVAL;
3c4390e8 196 vap->va_mode = vap->va_nlink = vap->va_uid = vap->va_gid =
83504fd5
KM
197 vap->va_fsid = vap->va_fileid =
198 vap->va_blocksize = vap->va_rdev =
ecf75a7d
KM
199 vap->va_atime.ts_sec = vap->va_atime.ts_nsec =
200 vap->va_mtime.ts_sec = vap->va_mtime.ts_nsec =
201 vap->va_ctime.ts_sec = vap->va_ctime.ts_nsec =
8cf4d4fb 202 vap->va_flags = vap->va_gen = VNOVAL;
fcba749b 203 vap->va_vaflags = 0;
3c4390e8 204}
c60798ca 205
36d09cb1
KM
206/*
207 * Routines having to do with the management of the vnode table.
208 */
9342689a 209extern int (**dead_vnodeop_p)();
32339c94 210extern void vclean();
1a80f56e 211long numvnodes;
e781da98 212extern struct vattr va_null;
3e787e54
KM
213int newnodes = 0;
214int printcnt = 0;
36d09cb1
KM
215
216/*
217 * Return the next vnode from the free list.
218 */
05560902 219int
36d09cb1
KM
220getnewvnode(tag, mp, vops, vpp)
221 enum vtagtype tag;
222 struct mount *mp;
cf74dd57 223 int (**vops)();
36d09cb1
KM
224 struct vnode **vpp;
225{
c768e50f 226 register struct vnode *vp;
1f9d2249 227 int s;
36d09cb1 228
3e787e54 229newnodes++;
3fc2ac18
KM
230 if ((vnode_free_list.tqh_first == NULL &&
231 numvnodes < 2 * desiredvnodes) ||
ecf75a7d 232 numvnodes < desiredvnodes) {
aacc1bff
KM
233 vp = (struct vnode *)malloc((u_long)sizeof *vp,
234 M_VNODE, M_WAITOK);
1a80f56e 235 bzero((char *)vp, sizeof *vp);
3e787e54
KM
236 vp->v_freelist.tqe_next = (struct vnode *)0xdeadf;
237 vp->v_freelist.tqe_prev = (struct vnode **)0xdeadb;
238 vp->v_mntvnodes.le_next = (struct vnode *)0xdeadf;
239 vp->v_mntvnodes.le_prev = (struct vnode **)0xdeadb;
1a80f56e 240 numvnodes++;
3e787e54 241 vp->v_spare[0] = numvnodes;
1a80f56e 242 } else {
3fc2ac18 243 if ((vp = vnode_free_list.tqh_first) == NULL) {
1a80f56e
KM
244 tablefull("vnode");
245 *vpp = 0;
246 return (ENFILE);
247 }
248 if (vp->v_usecount)
249 panic("free vnode isn't");
3e787e54
KM
250 if (vp->v_freelist.tqe_next == (struct vnode *)0xdeadf ||
251 vp->v_freelist.tqe_prev == (struct vnode **)0xdeadb)
252 panic("getnewvnode: not on queue");
3fc2ac18 253 TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
3e787e54 254 vp->v_freelist.tqe_next = (struct vnode *)0xdeadf;
0bf9bb76
KM
255 /* see comment on why 0xdeadb is set at end of vgone (below) */
256 vp->v_freelist.tqe_prev = (struct vnode **)0xdeadb;
39b99eb6 257 vp->v_lease = NULL;
1a80f56e
KM
258 if (vp->v_type != VBAD)
259 vgone(vp);
1f9d2249 260#ifdef DIAGNOSTIC
2345b093
KM
261 if (vp->v_data)
262 panic("cleaned vnode isn't");
1f9d2249
MS
263 s = splbio();
264 if (vp->v_numoutput)
265 panic("Clean vnode has pending I/O's");
266 splx(s);
267#endif
1a80f56e 268 vp->v_flag = 0;
1a80f56e 269 vp->v_lastr = 0;
2b5ada11
MH
270 vp->v_ralen = 0;
271 vp->v_maxra = 0;
1f9d2249
MS
272 vp->v_lastw = 0;
273 vp->v_lasta = 0;
274 vp->v_cstart = 0;
275 vp->v_clen = 0;
1a80f56e 276 vp->v_socket = 0;
36d09cb1 277 }
b027498b 278 vp->v_type = VNON;
36d09cb1
KM
279 cache_purge(vp);
280 vp->v_tag = tag;
ef24f6dd 281 vp->v_op = vops;
36d09cb1 282 insmntque(vp, mp);
36d09cb1 283 *vpp = vp;
0bf9bb76 284 vp->v_usecount = 1;
3fc2ac18 285 vp->v_data = 0;
3e787e54 286 if (printcnt-- > 0) vprint("getnewvnode got", vp);
36d09cb1
KM
287 return (0);
288}
8981e258 289
36d09cb1
KM
290/*
291 * Move a vnode from one mount queue to another.
292 */
05560902 293void
36d09cb1
KM
294insmntque(vp, mp)
295 register struct vnode *vp;
296 register struct mount *mp;
297{
36d09cb1
KM
298
299 /*
300 * Delete from old mount point vnode list, if on one.
301 */
3e787e54
KM
302 if (vp->v_mount != NULL) {
303 if (vp->v_mntvnodes.le_next == (struct vnode *)0xdeadf ||
304 vp->v_mntvnodes.le_prev == (struct vnode **)0xdeadb)
305 panic("insmntque: not on queue");
3fc2ac18 306 LIST_REMOVE(vp, v_mntvnodes);
3e787e54
KM
307 vp->v_mntvnodes.le_next = (struct vnode *)0xdeadf;
308 vp->v_mntvnodes.le_prev = (struct vnode **)0xdeadb;
309 }
36d09cb1
KM
310 /*
311 * Insert into list of vnodes for the new mount point, if available.
312 */
3fc2ac18 313 if ((vp->v_mount = mp) == NULL)
36d09cb1 314 return;
3e787e54
KM
315 if (vp->v_mntvnodes.le_next != (struct vnode *)0xdeadf ||
316 vp->v_mntvnodes.le_prev != (struct vnode **)0xdeadb)
317 panic("insmntque: already on queue");
3fc2ac18 318 LIST_INSERT_HEAD(&mp->mnt_vnodelist, vp, v_mntvnodes);
36d09cb1
KM
319}
320
76429560
KM
321/*
322 * Update outstanding I/O count and do wakeup if requested.
323 */
05560902 324void
76429560
KM
325vwakeup(bp)
326 register struct buf *bp;
327{
328 register struct vnode *vp;
329
a9338fad 330 bp->b_flags &= ~B_WRITEINPROG;
76429560 331 if (vp = bp->b_vp) {
05560902 332 if (--vp->v_numoutput < 0)
1f9d2249 333 panic("vwakeup: neg numoutput");
76429560
KM
334 if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) {
335 if (vp->v_numoutput < 0)
05560902 336 panic("vwakeup: neg numoutput 2");
76429560
KM
337 vp->v_flag &= ~VBWAIT;
338 wakeup((caddr_t)&vp->v_numoutput);
339 }
340 }
341}
342
76429560
KM
343/*
344 * Flush out and invalidate all buffers associated with a vnode.
345 * Called with the underlying object locked.
346 */
d024c2ce 347int
c33e9e8b 348vinvalbuf(vp, flags, cred, p, slpflag, slptimeo)
76429560 349 register struct vnode *vp;
12079a9d 350 int flags;
d024c2ce
KM
351 struct ucred *cred;
352 struct proc *p;
c33e9e8b 353 int slpflag, slptimeo;
76429560
KM
354{
355 register struct buf *bp;
356 struct buf *nbp, *blist;
d024c2ce 357 int s, error;
76429560 358
12079a9d 359 if (flags & V_SAVE) {
d024c2ce
KM
360 if (error = VOP_FSYNC(vp, cred, MNT_WAIT, p))
361 return (error);
3fc2ac18 362 if (vp->v_dirtyblkhd.lh_first != NULL)
d024c2ce
KM
363 panic("vinvalbuf: dirty bufs");
364 }
76429560 365 for (;;) {
3fc2ac18 366 if ((blist = vp->v_cleanblkhd.lh_first) && flags & V_SAVEMETA)
12079a9d 367 while (blist && blist->b_lblkno < 0)
3fc2ac18 368 blist = blist->b_vnbufs.le_next;
05560902 369 if (!blist && (blist = vp->v_dirtyblkhd.lh_first) &&
e3249ec0 370 (flags & V_SAVEMETA))
12079a9d 371 while (blist && blist->b_lblkno < 0)
3fc2ac18 372 blist = blist->b_vnbufs.le_next;
12079a9d 373 if (!blist)
76429560 374 break;
12079a9d 375
76429560 376 for (bp = blist; bp; bp = nbp) {
3fc2ac18 377 nbp = bp->b_vnbufs.le_next;
12079a9d
MS
378 if (flags & V_SAVEMETA && bp->b_lblkno < 0)
379 continue;
76429560
KM
380 s = splbio();
381 if (bp->b_flags & B_BUSY) {
382 bp->b_flags |= B_WANTED;
c33e9e8b
KM
383 error = tsleep((caddr_t)bp,
384 slpflag | (PRIBIO + 1), "vinvalbuf",
385 slptimeo);
76429560 386 splx(s);
c33e9e8b
KM
387 if (error)
388 return (error);
76429560
KM
389 break;
390 }
391 bremfree(bp);
392 bp->b_flags |= B_BUSY;
393 splx(s);
c33e9e8b
KM
394 /*
395 * XXX Since there are no node locks for NFS, I believe
396 * there is a slight chance that a delayed write will
397 * occur while sleeping just above, so check for it.
398 */
399 if ((bp->b_flags & B_DELWRI) && (flags & V_SAVE)) {
400 (void) VOP_BWRITE(bp);
401 break;
402 }
12079a9d 403 bp->b_flags |= B_INVAL;
76429560
KM
404 brelse(bp);
405 }
406 }
e3249ec0 407 if (!(flags & V_SAVEMETA) &&
3fc2ac18 408 (vp->v_dirtyblkhd.lh_first || vp->v_cleanblkhd.lh_first))
76429560 409 panic("vinvalbuf: flush failed");
d024c2ce 410 return (0);
76429560
KM
411}
412
413/*
414 * Associate a buffer with a vnode.
415 */
05560902 416void
76429560
KM
417bgetvp(vp, bp)
418 register struct vnode *vp;
419 register struct buf *bp;
420{
421
422 if (bp->b_vp)
423 panic("bgetvp: not free");
424 VHOLD(vp);
425 bp->b_vp = vp;
426 if (vp->v_type == VBLK || vp->v_type == VCHR)
427 bp->b_dev = vp->v_rdev;
428 else
429 bp->b_dev = NODEV;
430 /*
431 * Insert onto list for new vnode.
432 */
e3249ec0 433 bufinsvn(bp, &vp->v_cleanblkhd);
76429560
KM
434}
435
436/*
437 * Disassociate a buffer from a vnode.
438 */
05560902 439void
76429560
KM
440brelvp(bp)
441 register struct buf *bp;
442{
76429560
KM
443 struct vnode *vp;
444
445 if (bp->b_vp == (struct vnode *) 0)
446 panic("brelvp: NULL");
447 /*
448 * Delete from old vnode list, if on one.
449 */
3fc2ac18 450 if (bp->b_vnbufs.le_next != NOLIST)
e3249ec0 451 bufremvn(bp);
76429560
KM
452 vp = bp->b_vp;
453 bp->b_vp = (struct vnode *) 0;
454 HOLDRELE(vp);
455}
456
457/*
458 * Reassign a buffer from one vnode to another.
459 * Used to assign file specific control information
460 * (indirect blocks) to the vnode to which they belong.
461 */
05560902 462void
76429560
KM
463reassignbuf(bp, newvp)
464 register struct buf *bp;
465 register struct vnode *newvp;
466{
3fc2ac18 467 register struct buflists *listheadp;
76429560 468
e5c3f16e
KM
469 if (newvp == NULL) {
470 printf("reassignbuf: NULL");
471 return;
472 }
76429560
KM
473 /*
474 * Delete from old vnode list, if on one.
475 */
3fc2ac18 476 if (bp->b_vnbufs.le_next != NOLIST)
e3249ec0 477 bufremvn(bp);
76429560
KM
478 /*
479 * If dirty, put on list of dirty buffers;
480 * otherwise insert onto list of clean buffers.
481 */
482 if (bp->b_flags & B_DELWRI)
483 listheadp = &newvp->v_dirtyblkhd;
484 else
485 listheadp = &newvp->v_cleanblkhd;
e3249ec0 486 bufinsvn(bp, listheadp);
76429560
KM
487}
488
36d09cb1 489/*
ef24f6dd
KM
490 * Create a vnode for a block device.
491 * Used for root filesystem, argdev, and swap areas.
492 * Also used for memory file system special devices.
493 */
05560902 494int
ef24f6dd
KM
495bdevvp(dev, vpp)
496 dev_t dev;
497 struct vnode **vpp;
498{
ef24f6dd
KM
499 register struct vnode *vp;
500 struct vnode *nvp;
501 int error;
502
1c89915d
KM
503 if (dev == NODEV)
504 return (0);
9342689a 505 error = getnewvnode(VT_NON, (struct mount *)0, spec_vnodeop_p, &nvp);
ef24f6dd 506 if (error) {
05560902 507 *vpp = NULLVP;
ef24f6dd
KM
508 return (error);
509 }
510 vp = nvp;
511 vp->v_type = VBLK;
c0de8792 512 if (nvp = checkalias(vp, dev, (struct mount *)0)) {
ef24f6dd
KM
513 vput(vp);
514 vp = nvp;
515 }
516 *vpp = vp;
517 return (0);
518}
519
520/*
521 * Check to see if the new vnode represents a special device
522 * for which we already have a vnode (either because of
523 * bdevvp() or because of a different vnode representing
524 * the same block device). If such an alias exists, deallocate
f0556f86 525 * the existing contents and return the aliased vnode. The
ef24f6dd
KM
526 * caller is responsible for filling it with its new contents.
527 */
528struct vnode *
c0de8792 529checkalias(nvp, nvp_rdev, mp)
ef24f6dd 530 register struct vnode *nvp;
c0de8792 531 dev_t nvp_rdev;
ef24f6dd
KM
532 struct mount *mp;
533{
534 register struct vnode *vp;
c0de8792 535 struct vnode **vpp;
ef24f6dd
KM
536
537 if (nvp->v_type != VBLK && nvp->v_type != VCHR)
54fb9dc2 538 return (NULLVP);
c0de8792
KM
539
540 vpp = &speclisth[SPECHASH(nvp_rdev)];
ef24f6dd 541loop:
c0de8792
KM
542 for (vp = *vpp; vp; vp = vp->v_specnext) {
543 if (nvp_rdev != vp->v_rdev || nvp->v_type != vp->v_type)
ef24f6dd 544 continue;
c0de8792
KM
545 /*
546 * Alias, but not in use, so flush it out.
547 */
7f7b7d89 548 if (vp->v_usecount == 0) {
c0de8792
KM
549 vgone(vp);
550 goto loop;
551 }
3fc2ac18 552 if (vget(vp, 1))
ef62830d 553 goto loop;
ef24f6dd
KM
554 break;
555 }
c0de8792 556 if (vp == NULL || vp->v_tag != VT_NON) {
c0de8792
KM
557 MALLOC(nvp->v_specinfo, struct specinfo *,
558 sizeof(struct specinfo), M_VNODE, M_WAITOK);
559 nvp->v_rdev = nvp_rdev;
7f7b7d89 560 nvp->v_hashchain = vpp;
c0de8792 561 nvp->v_specnext = *vpp;
2c957a90 562 nvp->v_specflags = 0;
c0de8792 563 *vpp = nvp;
40452d5e
KM
564 if (vp != NULL) {
565 nvp->v_flag |= VALIASED;
566 vp->v_flag |= VALIASED;
567 vput(vp);
568 }
54fb9dc2 569 return (NULLVP);
ef24f6dd 570 }
2bae1875
KM
571 VOP_UNLOCK(vp);
572 vclean(vp, 0);
ef24f6dd
KM
573 vp->v_op = nvp->v_op;
574 vp->v_tag = nvp->v_tag;
575 nvp->v_type = VNON;
576 insmntque(vp, mp);
577 return (vp);
578}
579
580/*
581 * Grab a particular vnode from the free list, increment its
582 * reference count and lock it. The vnode lock bit is set the
583 * vnode is being eliminated in vgone. The process is awakened
584 * when the transition is completed, and an error returned to
585 * indicate that the vnode is no longer usable (possibly having
586 * been changed to a new file system type).
36d09cb1 587 */
05560902 588int
3fc2ac18 589vget(vp, lockflag)
36d09cb1 590 register struct vnode *vp;
3fc2ac18 591 int lockflag;
36d09cb1 592{
36d09cb1 593
9130defb
KM
594 /*
595 * If the vnode is in the process of being cleaned out for
596 * another use, we wait for the cleaning to finish and then
597 * return failure. Cleaning is determined either by checking
598 * that the VXLOCK flag is set, or that the use count is
599 * zero with the back pointer set to show that it has been
600 * removed from the free list by getnewvnode. The VXLOCK
601 * flag may not have been set yet because vclean is blocked in
602 * the VOP_LOCK call waiting for the VOP_INACTIVE to complete.
603 */
604 if ((vp->v_flag & VXLOCK) ||
605 (vp->v_usecount == 0 &&
606 vp->v_freelist.tqe_prev == (struct vnode **)0xdeadb)) {
ef24f6dd 607 vp->v_flag |= VXWANT;
05560902 608 tsleep((caddr_t)vp, PINOD, "vget", 0);
ef24f6dd
KM
609 return (1);
610 }
3e787e54
KM
611 if (vp->v_usecount == 0) {
612 if (vp->v_freelist.tqe_next == (struct vnode *)0xdeadf ||
613 vp->v_freelist.tqe_prev == (struct vnode **)0xdeadb)
614 panic("vget: not on queue");
3fc2ac18 615 TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
3e787e54
KM
616 vp->v_freelist.tqe_next = (struct vnode *)0xdeadf;
617 vp->v_freelist.tqe_prev = (struct vnode **)0xdeadb;
618 }
ec04fc59 619 vp->v_usecount++;
3fc2ac18
KM
620 if (lockflag)
621 VOP_LOCK(vp);
3e787e54 622 if (printcnt-- > 0) vprint("vget got", vp);
ef24f6dd 623 return (0);
36d09cb1
KM
624}
625
d32390ea
KM
626int bug_refs = 0;
627
36d09cb1
KM
628/*
629 * Vnode reference, just increment the count
630 */
05560902
CD
631void
632vref(vp)
36d09cb1
KM
633 struct vnode *vp;
634{
635
ec04fc59
KM
636 if (vp->v_usecount <= 0)
637 panic("vref used where vget required");
3e787e54
KM
638 if (vp->v_freelist.tqe_next != (struct vnode *)0xdeadf ||
639 vp->v_freelist.tqe_prev != (struct vnode **)0xdeadb)
640 panic("vref: not free");
7f7b7d89 641 vp->v_usecount++;
3e787e54 642 if (printcnt-- > 0) vprint("vref get", vp);
d32390ea
KM
643 if (vp->v_type != VBLK && curproc)
644 curproc->p_spare[0]++;
645 if (bug_refs)
646 vprint("vref: ");
36d09cb1
KM
647}
648
649/*
650 * vput(), just unlock and vrele()
651 */
05560902
CD
652void
653vput(vp)
36d09cb1
KM
654 register struct vnode *vp;
655{
4d1ee2eb 656
36d09cb1
KM
657 VOP_UNLOCK(vp);
658 vrele(vp);
659}
660
661/*
662 * Vnode release.
663 * If count drops to zero, call inactive routine and return to freelist.
664 */
05560902
CD
665void
666vrele(vp)
36d09cb1
KM
667 register struct vnode *vp;
668{
669
65c3b3a8 670#ifdef DIAGNOSTIC
36d09cb1 671 if (vp == NULL)
ef24f6dd 672 panic("vrele: null vp");
65c3b3a8 673#endif
7f7b7d89 674 vp->v_usecount--;
3e787e54 675 if (printcnt-- > 0) vprint("vrele put", vp);
d32390ea
KM
676 if (vp->v_type != VBLK && curproc)
677 curproc->p_spare[0]--;
678 if (bug_refs)
679 vprint("vref: ");
7f7b7d89 680 if (vp->v_usecount > 0)
36d09cb1 681 return;
65c3b3a8
KM
682#ifdef DIAGNOSTIC
683 if (vp->v_usecount != 0 || vp->v_writecount != 0) {
684 vprint("vrele: bad ref count", vp);
685 panic("vrele: ref cnt");
686 }
687#endif
dc998e72
KM
688 /*
689 * insert at tail of LRU list
690 */
3e787e54
KM
691 if (vp->v_freelist.tqe_next != (struct vnode *)0xdeadf ||
692 vp->v_freelist.tqe_prev != (struct vnode **)0xdeadb)
693 panic("vrele: not free");
3fc2ac18 694 TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
d024c2ce 695 VOP_INACTIVE(vp);
ef24f6dd
KM
696}
697
7f7b7d89
KM
698/*
699 * Page or buffer structure gets a reference.
700 */
05560902
CD
701void
702vhold(vp)
7f7b7d89
KM
703 register struct vnode *vp;
704{
705
706 vp->v_holdcnt++;
707}
708
709/*
710 * Page or buffer structure frees a reference.
711 */
05560902
CD
712void
713holdrele(vp)
7f7b7d89
KM
714 register struct vnode *vp;
715{
716
717 if (vp->v_holdcnt <= 0)
718 panic("holdrele: holdcnt");
719 vp->v_holdcnt--;
720}
721
f0556f86
KM
722/*
723 * Remove any vnodes in the vnode table belonging to mount point mp.
724 *
725 * If MNT_NOFORCE is specified, there should not be any active ones,
726 * return error if any are found (nb: this is a user error, not a
727 * system error). If MNT_FORCE is specified, detach any active vnodes
728 * that are found.
729 */
8981e258 730#ifdef DIAGNOSTIC
bb4964fd
KM
731int busyprt = 0; /* print out busy vnodes */
732struct ctldebug debug1 = { "busyprt", &busyprt };
8981e258 733#endif
f0556f86 734
05560902 735int
f0556f86
KM
736vflush(mp, skipvp, flags)
737 struct mount *mp;
738 struct vnode *skipvp;
739 int flags;
740{
741 register struct vnode *vp, *nvp;
742 int busy = 0;
743
54fb9dc2 744 if ((mp->mnt_flag & MNT_MPBUSY) == 0)
36ef03ec 745 panic("vflush: not busy");
4597dd33 746loop:
3fc2ac18 747 for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) {
4597dd33
KM
748 if (vp->v_mount != mp)
749 goto loop;
3fc2ac18 750 nvp = vp->v_mntvnodes.le_next;
f0556f86
KM
751 /*
752 * Skip over a selected vnode.
f0556f86
KM
753 */
754 if (vp == skipvp)
755 continue;
36ef03ec
KM
756 /*
757 * Skip over a vnodes marked VSYSTEM.
758 */
759 if ((flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM))
760 continue;
da374605
KM
761 /*
762 * If WRITECLOSE is set, only flush out regular file
763 * vnodes open for writing.
764 */
765 if ((flags & WRITECLOSE) &&
766 (vp->v_writecount == 0 || vp->v_type != VREG))
767 continue;
f0556f86 768 /*
7f7b7d89 769 * With v_usecount == 0, all we need to do is clear
f0556f86
KM
770 * out the vnode data structures and we are done.
771 */
7f7b7d89 772 if (vp->v_usecount == 0) {
f0556f86
KM
773 vgone(vp);
774 continue;
775 }
776 /*
da374605 777 * If FORCECLOSE is set, forcibly close the vnode.
f0556f86
KM
778 * For block or character devices, revert to an
779 * anonymous device. For all other files, just kill them.
780 */
36ef03ec 781 if (flags & FORCECLOSE) {
f0556f86
KM
782 if (vp->v_type != VBLK && vp->v_type != VCHR) {
783 vgone(vp);
784 } else {
785 vclean(vp, 0);
9342689a 786 vp->v_op = spec_vnodeop_p;
f0556f86
KM
787 insmntque(vp, (struct mount *)0);
788 }
789 continue;
790 }
8981e258 791#ifdef DIAGNOSTIC
f0556f86 792 if (busyprt)
0bf84b18 793 vprint("vflush: busy vnode", vp);
8981e258 794#endif
f0556f86
KM
795 busy++;
796 }
797 if (busy)
798 return (EBUSY);
799 return (0);
800}
801
ef24f6dd
KM
802/*
803 * Disassociate the underlying file system from a vnode.
ef24f6dd 804 */
ecf75a7d
KM
805void
806vclean(vp, flags)
ef24f6dd 807 register struct vnode *vp;
aacc1bff 808 int flags;
ef24f6dd 809{
2bae1875 810 int active;
ef24f6dd 811
2bae1875
KM
812 /*
813 * Check to see if the vnode is in use.
0bf84b18
KM
814 * If so we have to reference it before we clean it out
815 * so that its count cannot fall to zero and generate a
816 * race against ourselves to recycle it.
2bae1875 817 */
7f7b7d89 818 if (active = vp->v_usecount)
2bae1875 819 VREF(vp);
669df1aa
KM
820 /*
821 * Even if the count is zero, the VOP_INACTIVE routine may still
822 * have the object locked while it cleans it out. The VOP_LOCK
823 * ensures that the VOP_INACTIVE routine is done with its work.
824 * For active vnodes, it ensures that no other activity can
825 * occur while the underlying object is being cleaned out.
826 */
827 VOP_LOCK(vp);
2bae1875
KM
828 /*
829 * Prevent the vnode from being recycled or
830 * brought into use while we clean it out.
831 */
0bf84b18
KM
832 if (vp->v_flag & VXLOCK)
833 panic("vclean: deadlock");
ef24f6dd 834 vp->v_flag |= VXLOCK;
0bf84b18 835 /*
669df1aa 836 * Clean out any buffers associated with the vnode.
0bf84b18 837 */
36ef03ec 838 if (flags & DOCLOSE)
c33e9e8b 839 vinvalbuf(vp, V_SAVE, NOCRED, NULL, 0, 0);
ef24f6dd 840 /*
669df1aa
KM
841 * Any other processes trying to obtain this lock must first
842 * wait for VXLOCK to clear, then call the new lock operation.
ef24f6dd 843 */
669df1aa 844 VOP_UNLOCK(vp);
ef24f6dd 845 /*
669df1aa
KM
846 * If purging an active vnode, it must be closed and
847 * deactivated before being reclaimed.
ef24f6dd 848 */
2bae1875 849 if (active) {
669df1aa
KM
850 if (flags & DOCLOSE)
851 VOP_CLOSE(vp, IO_NDELAY, NOCRED, NULL);
852 VOP_INACTIVE(vp);
ef24f6dd
KM
853 }
854 /*
855 * Reclaim the vnode.
856 */
669df1aa 857 if (VOP_RECLAIM(vp))
ef24f6dd 858 panic("vclean: cannot reclaim");
2bae1875
KM
859 if (active)
860 vrele(vp);
38c46eee 861
ef24f6dd 862 /*
669df1aa 863 * Done with purge, notify sleepers of the grim news.
ef24f6dd 864 */
669df1aa
KM
865 vp->v_op = dead_vnodeop_p;
866 vp->v_tag = VT_NON;
ef24f6dd
KM
867 vp->v_flag &= ~VXLOCK;
868 if (vp->v_flag & VXWANT) {
869 vp->v_flag &= ~VXWANT;
870 wakeup((caddr_t)vp);
871 }
872}
873
ef62830d
KM
874/*
875 * Eliminate all activity associated with the requested vnode
876 * and with all vnodes aliased to the requested vnode.
877 */
05560902
CD
878void
879vgoneall(vp)
ef62830d
KM
880 register struct vnode *vp;
881{
7f7b7d89 882 register struct vnode *vq;
ef62830d 883
7a7b3a95
KM
884 if (vp->v_flag & VALIASED) {
885 /*
886 * If a vgone (or vclean) is already in progress,
887 * wait until it is done and return.
888 */
889 if (vp->v_flag & VXLOCK) {
890 vp->v_flag |= VXWANT;
05560902 891 tsleep((caddr_t)vp, PINOD, "vgoneall", 0);
7a7b3a95
KM
892 return;
893 }
894 /*
895 * Ensure that vp will not be vgone'd while we
896 * are eliminating its aliases.
897 */
898 vp->v_flag |= VXLOCK;
899 while (vp->v_flag & VALIASED) {
900 for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
901 if (vq->v_rdev != vp->v_rdev ||
902 vq->v_type != vp->v_type || vp == vq)
903 continue;
904 vgone(vq);
905 break;
906 }
ef62830d 907 }
7a7b3a95
KM
908 /*
909 * Remove the lock so that vgone below will
910 * really eliminate the vnode after which time
911 * vgone will awaken any sleepers.
912 */
913 vp->v_flag &= ~VXLOCK;
ef62830d
KM
914 }
915 vgone(vp);
916}
917
ef24f6dd
KM
918/*
919 * Eliminate all activity associated with a vnode
920 * in preparation for reuse.
921 */
05560902
CD
922void
923vgone(vp)
ef24f6dd
KM
924 register struct vnode *vp;
925{
7f7b7d89 926 register struct vnode *vq;
c0de8792 927 struct vnode *vx;
ef24f6dd 928
4f55e3ec
KM
929 /*
930 * If a vgone (or vclean) is already in progress,
931 * wait until it is done and return.
932 */
933 if (vp->v_flag & VXLOCK) {
934 vp->v_flag |= VXWANT;
05560902 935 tsleep((caddr_t)vp, PINOD, "vgone", 0);
4f55e3ec
KM
936 return;
937 }
ef24f6dd
KM
938 /*
939 * Clean out the filesystem specific data.
940 */
36ef03ec 941 vclean(vp, DOCLOSE);
ef24f6dd
KM
942 /*
943 * Delete from old mount point vnode list, if on one.
944 */
3fc2ac18 945 if (vp->v_mount != NULL) {
3e787e54
KM
946 if (vp->v_mntvnodes.le_next == (struct vnode *)0xdeadf ||
947 vp->v_mntvnodes.le_prev == (struct vnode **)0xdeadb)
948 panic("vgone: not on queue");
3fc2ac18 949 LIST_REMOVE(vp, v_mntvnodes);
3e787e54
KM
950 vp->v_mntvnodes.le_next = (struct vnode *)0xdeadf;
951 vp->v_mntvnodes.le_prev = (struct vnode **)0xdeadb;
d10e9258 952 vp->v_mount = NULL;
ef24f6dd
KM
953 }
954 /*
955 * If special device, remove it from special device alias list.
956 */
957 if (vp->v_type == VBLK || vp->v_type == VCHR) {
7f7b7d89
KM
958 if (*vp->v_hashchain == vp) {
959 *vp->v_hashchain = vp->v_specnext;
ef24f6dd 960 } else {
7f7b7d89 961 for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
c0de8792 962 if (vq->v_specnext != vp)
ef24f6dd 963 continue;
c0de8792 964 vq->v_specnext = vp->v_specnext;
ef24f6dd
KM
965 break;
966 }
c0de8792 967 if (vq == NULL)
ef24f6dd
KM
968 panic("missing bdev");
969 }
c0de8792 970 if (vp->v_flag & VALIASED) {
4d1ee2eb 971 vx = NULL;
7f7b7d89 972 for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
de81e10c
KM
973 if (vq->v_rdev != vp->v_rdev ||
974 vq->v_type != vp->v_type)
c0de8792 975 continue;
4d1ee2eb
CT
976 if (vx)
977 break;
c0de8792
KM
978 vx = vq;
979 }
4d1ee2eb 980 if (vx == NULL)
c0de8792 981 panic("missing alias");
4d1ee2eb 982 if (vq == NULL)
c0de8792
KM
983 vx->v_flag &= ~VALIASED;
984 vp->v_flag &= ~VALIASED;
985 }
986 FREE(vp->v_specinfo, M_VNODE);
987 vp->v_specinfo = NULL;
ef24f6dd
KM
988 }
989 /*
3387ef89 990 * If it is on the freelist and not already at the head,
0bf9bb76
KM
991 * move it to the head of the list. The test of the back
992 * pointer and the reference count of zero is because
993 * it will be removed from the free list by getnewvnode,
994 * but will not have its reference count incremented until
995 * after calling vgone. If the reference count were
996 * incremented first, vgone would (incorrectly) try to
997 * close the previous instance of the underlying object.
998 * So, the back pointer is explicitly set to `0xdeadb' in
999 * getnewvnode after removing it from the freelist to ensure
1000 * that we do not try to move it here.
ef24f6dd 1001 */
0bf9bb76
KM
1002 if (vp->v_usecount == 0 &&
1003 vp->v_freelist.tqe_prev != (struct vnode **)0xdeadb &&
1004 vnode_free_list.tqh_first != vp) {
3e787e54
KM
1005 if (vp->v_freelist.tqe_next == (struct vnode *)0xdeadf)
1006 panic("vgone: use 0, not free");
3fc2ac18
KM
1007 TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
1008 TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
ef24f6dd 1009 }
2bae1875 1010 vp->v_type = VBAD;
36d09cb1 1011}
ef62830d 1012
2bcd6066
KM
1013/*
1014 * Lookup a vnode by device number.
1015 */
05560902 1016int
2bcd6066
KM
1017vfinddev(dev, type, vpp)
1018 dev_t dev;
1019 enum vtype type;
1020 struct vnode **vpp;
1021{
1022 register struct vnode *vp;
1023
1024 for (vp = speclisth[SPECHASH(dev)]; vp; vp = vp->v_specnext) {
1025 if (dev != vp->v_rdev || type != vp->v_type)
1026 continue;
1027 *vpp = vp;
05378ee4 1028 return (1);
2bcd6066 1029 }
05378ee4 1030 return (0);
2bcd6066
KM
1031}
1032
ef62830d
KM
1033/*
1034 * Calculate the total number of references to a special device.
1035 */
05560902 1036int
ef62830d
KM
1037vcount(vp)
1038 register struct vnode *vp;
1039{
1d2d7c6d 1040 register struct vnode *vq, *vnext;
ef62830d
KM
1041 int count;
1042
1d2d7c6d 1043loop:
ef62830d 1044 if ((vp->v_flag & VALIASED) == 0)
7f7b7d89 1045 return (vp->v_usecount);
1d2d7c6d
KM
1046 for (count = 0, vq = *vp->v_hashchain; vq; vq = vnext) {
1047 vnext = vq->v_specnext;
de81e10c 1048 if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type)
ef62830d
KM
1049 continue;
1050 /*
1051 * Alias, but not in use, so flush it out.
1052 */
1d2d7c6d 1053 if (vq->v_usecount == 0 && vq != vp) {
ef62830d
KM
1054 vgone(vq);
1055 goto loop;
1056 }
7f7b7d89 1057 count += vq->v_usecount;
ef62830d
KM
1058 }
1059 return (count);
1060}
0bf84b18
KM
1061
1062/*
1063 * Print out a description of a vnode.
1064 */
1065static char *typename[] =
61f846a8 1066 { "VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD" };
0bf84b18 1067
5d263ebe 1068void
0bf84b18
KM
1069vprint(label, vp)
1070 char *label;
1071 register struct vnode *vp;
1072{
f2f730c6 1073 char buf[64];
0bf84b18
KM
1074
1075 if (label != NULL)
1076 printf("%s: ", label);
3e787e54 1077 printf("num %d ", vp->v_spare[0]);
65c3b3a8
KM
1078 printf("type %s, usecount %d, writecount %d, refcount %d,",
1079 typename[vp->v_type], vp->v_usecount, vp->v_writecount,
1080 vp->v_holdcnt);
f2f730c6
KM
1081 buf[0] = '\0';
1082 if (vp->v_flag & VROOT)
1083 strcat(buf, "|VROOT");
1084 if (vp->v_flag & VTEXT)
1085 strcat(buf, "|VTEXT");
36ef03ec
KM
1086 if (vp->v_flag & VSYSTEM)
1087 strcat(buf, "|VSYSTEM");
36ef03ec
KM
1088 if (vp->v_flag & VXLOCK)
1089 strcat(buf, "|VXLOCK");
1090 if (vp->v_flag & VXWANT)
1091 strcat(buf, "|VXWANT");
f2f730c6
KM
1092 if (vp->v_flag & VBWAIT)
1093 strcat(buf, "|VBWAIT");
36ef03ec
KM
1094 if (vp->v_flag & VALIASED)
1095 strcat(buf, "|VALIASED");
f2f730c6
KM
1096 if (buf[0] != '\0')
1097 printf(" flags (%s)", &buf[1]);
3fc2ac18
KM
1098 if (vp->v_data == NULL) {
1099 printf("\n");
1100 } else {
1101 printf("\n\t");
1102 VOP_PRINT(vp);
1103 }
0bf84b18 1104}
985cbdd5 1105
34c62e18
KM
1106#ifdef DEBUG
1107/*
1108 * List all of the locked vnodes in the system.
1109 * Called when debugging the kernel.
1110 */
05560902 1111void
34c62e18
KM
1112printlockedvnodes()
1113{
1114 register struct mount *mp;
1115 register struct vnode *vp;
1116
1117 printf("Locked vnodes\n");
3fc2ac18
KM
1118 for (mp = mountlist.tqh_first; mp != NULL; mp = mp->mnt_list.tqe_next) {
1119 for (vp = mp->mnt_vnodelist.lh_first;
1120 vp != NULL;
1121 vp = vp->v_mntvnodes.le_next)
34c62e18
KM
1122 if (VOP_ISLOCKED(vp))
1123 vprint((char *)0, vp);
3fc2ac18 1124 }
34c62e18
KM
1125}
1126#endif
1127
985cbdd5
MT
1128int kinfo_vdebug = 1;
1129int kinfo_vgetfailed;
1130#define KINFO_VNODESLOP 10
1131/*
786fb484 1132 * Dump vnode list (via sysctl).
985cbdd5
MT
1133 * Copyout address of vnode followed by vnode.
1134 */
aacc1bff 1135/* ARGSUSED */
05560902 1136int
786fb484 1137sysctl_vnode(where, sizep)
985cbdd5 1138 char *where;
c1909da4 1139 size_t *sizep;
985cbdd5 1140{
3fc2ac18 1141 register struct mount *mp, *nmp;
985cbdd5 1142 struct vnode *vp;
985cbdd5 1143 register char *bp = where, *savebp;
5bf57294 1144 char *ewhere;
985cbdd5
MT
1145 int error;
1146
1147#define VPTRSZ sizeof (struct vnode *)
1148#define VNODESZ sizeof (struct vnode)
1149 if (where == NULL) {
786fb484 1150 *sizep = (numvnodes + KINFO_VNODESLOP) * (VPTRSZ + VNODESZ);
985cbdd5
MT
1151 return (0);
1152 }
786fb484 1153 ewhere = where + *sizep;
985cbdd5 1154
3fc2ac18
KM
1155 for (mp = mountlist.tqh_first; mp != NULL; mp = nmp) {
1156 nmp = mp->mnt_list.tqe_next;
1157 if (vfs_busy(mp))
36ef03ec 1158 continue;
985cbdd5
MT
1159 savebp = bp;
1160again:
3fc2ac18
KM
1161 for (vp = mp->mnt_vnodelist.lh_first;
1162 vp != NULL;
1163 vp = vp->v_mntvnodes.le_next) {
41185b3b
KM
1164 /*
1165 * Check that the vp is still associated with
1166 * this filesystem. RACE: could have been
1167 * recycled onto the same filesystem.
1168 */
4597dd33
KM
1169 if (vp->v_mount != mp) {
1170 if (kinfo_vdebug)
1171 printf("kinfo: vp changed\n");
1172 bp = savebp;
1173 goto again;
1174 }
786fb484
KM
1175 if (bp + VPTRSZ + VNODESZ > ewhere) {
1176 *sizep = bp - where;
1177 return (ENOMEM);
1178 }
1179 if ((error = copyout((caddr_t)&vp, bp, VPTRSZ)) ||
1180 (error = copyout((caddr_t)vp, bp + VPTRSZ, VNODESZ)))
985cbdd5 1181 return (error);
985cbdd5 1182 bp += VPTRSZ + VNODESZ;
985cbdd5 1183 }
3fc2ac18
KM
1184 vfs_unbusy(mp);
1185 }
985cbdd5 1186
786fb484 1187 *sizep = bp - where;
985cbdd5
MT
1188 return (0);
1189}
8981e258
MH
1190
1191/*
1192 * Check to see if a filesystem is mounted on a block device.
1193 */
1194int
1195vfs_mountedon(vp)
1196 register struct vnode *vp;
1197{
1198 register struct vnode *vq;
1199
1200 if (vp->v_specflags & SI_MOUNTEDON)
1201 return (EBUSY);
1202 if (vp->v_flag & VALIASED) {
1203 for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
1204 if (vq->v_rdev != vp->v_rdev ||
1205 vq->v_type != vp->v_type)
1206 continue;
1207 if (vq->v_specflags & SI_MOUNTEDON)
1208 return (EBUSY);
1209 }
1210 }
1211 return (0);
1212}
1213
1214/*
1215 * Build hash lists of net addresses and hang them off the mount point.
1216 * Called by ufs_mount() to set up the lists of export addresses.
1217 */
1218static int
1219vfs_hang_addrlist(mp, nep, argp)
1220 struct mount *mp;
1221 struct netexport *nep;
1222 struct export_args *argp;
1223{
1224 register struct netcred *np;
1225 register struct radix_node_head *rnh;
1226 register int i;
1227 struct radix_node *rn;
1228 struct sockaddr *saddr, *smask = 0;
1229 struct domain *dom;
1230 int error;
1231
1232 if (argp->ex_addrlen == 0) {
1233 if (mp->mnt_flag & MNT_DEFEXPORTED)
1234 return (EPERM);
1235 np = &nep->ne_defexported;
1236 np->netc_exflags = argp->ex_flags;
1237 np->netc_anon = argp->ex_anon;
1238 np->netc_anon.cr_ref = 1;
1239 mp->mnt_flag |= MNT_DEFEXPORTED;
1240 return (0);
1241 }
1242 i = sizeof(struct netcred) + argp->ex_addrlen + argp->ex_masklen;
1243 np = (struct netcred *)malloc(i, M_NETADDR, M_WAITOK);
1244 bzero((caddr_t)np, i);
1245 saddr = (struct sockaddr *)(np + 1);
1246 if (error = copyin(argp->ex_addr, (caddr_t)saddr, argp->ex_addrlen))
1247 goto out;
1248 if (saddr->sa_len > argp->ex_addrlen)
1249 saddr->sa_len = argp->ex_addrlen;
1250 if (argp->ex_masklen) {
1251 smask = (struct sockaddr *)((caddr_t)saddr + argp->ex_addrlen);
1252 error = copyin(argp->ex_addr, (caddr_t)smask, argp->ex_masklen);
1253 if (error)
1254 goto out;
1255 if (smask->sa_len > argp->ex_masklen)
1256 smask->sa_len = argp->ex_masklen;
1257 }
1258 i = saddr->sa_family;
1259 if ((rnh = nep->ne_rtable[i]) == 0) {
1260 /*
1261 * Seems silly to initialize every AF when most are not
1262 * used, do so on demand here
1263 */
1264 for (dom = domains; dom; dom = dom->dom_next)
1265 if (dom->dom_family == i && dom->dom_rtattach) {
1266 dom->dom_rtattach((void **)&nep->ne_rtable[i],
1267 dom->dom_rtoffset);
1268 break;
1269 }
1270 if ((rnh = nep->ne_rtable[i]) == 0) {
1271 error = ENOBUFS;
1272 goto out;
1273 }
1274 }
1275 rn = (*rnh->rnh_addaddr)((caddr_t)saddr, (caddr_t)smask, rnh,
1276 np->netc_rnodes);
1277 if (rn == 0 || np != (struct netcred *)rn) { /* already exists */
1278 error = EPERM;
1279 goto out;
1280 }
1281 np->netc_exflags = argp->ex_flags;
1282 np->netc_anon = argp->ex_anon;
1283 np->netc_anon.cr_ref = 1;
1284 return (0);
1285out:
1286 free(np, M_NETADDR);
1287 return (error);
1288}
1289
1290/* ARGSUSED */
1291static int
1292vfs_free_netcred(rn, w)
1293 struct radix_node *rn;
1294 caddr_t w;
1295{
1296 register struct radix_node_head *rnh = (struct radix_node_head *)w;
1297
1298 (*rnh->rnh_deladdr)(rn->rn_key, rn->rn_mask, rnh);
1299 free((caddr_t)rn, M_NETADDR);
1300 return (0);
1301}
05560902 1302
8981e258
MH
1303/*
1304 * Free the net address hash lists that are hanging off the mount points.
1305 */
1306static void
1307vfs_free_addrlist(nep)
1308 struct netexport *nep;
1309{
1310 register int i;
1311 register struct radix_node_head *rnh;
1312
1313 for (i = 0; i <= AF_MAX; i++)
1314 if (rnh = nep->ne_rtable[i]) {
1315 (*rnh->rnh_walktree)(rnh, vfs_free_netcred,
1316 (caddr_t)rnh);
1317 free((caddr_t)rnh, M_RTABLE);
1318 nep->ne_rtable[i] = 0;
1319 }
1320}
1321
1322int
1323vfs_export(mp, nep, argp)
1324 struct mount *mp;
1325 struct netexport *nep;
1326 struct export_args *argp;
1327{
1328 int error;
1329
1330 if (argp->ex_flags & MNT_DELEXPORT) {
1331 vfs_free_addrlist(nep);
1332 mp->mnt_flag &= ~(MNT_EXPORTED | MNT_DEFEXPORTED);
1333 }
1334 if (argp->ex_flags & MNT_EXPORTED) {
1335 if (error = vfs_hang_addrlist(mp, nep, argp))
1336 return (error);
1337 mp->mnt_flag |= MNT_EXPORTED;
1338 }
1339 return (0);
1340}
1341
1342struct netcred *
1343vfs_export_lookup(mp, nep, nam)
1344 register struct mount *mp;
1345 struct netexport *nep;
1346 struct mbuf *nam;
1347{
1348 register struct netcred *np;
1349 register struct radix_node_head *rnh;
1350 struct sockaddr *saddr;
1351
1352 np = NULL;
1353 if (mp->mnt_flag & MNT_EXPORTED) {
1354 /*
1355 * Lookup in the export list first.
1356 */
1357 if (nam != NULL) {
1358 saddr = mtod(nam, struct sockaddr *);
1359 rnh = nep->ne_rtable[saddr->sa_family];
1360 if (rnh != NULL) {
1361 np = (struct netcred *)
1362 (*rnh->rnh_matchaddr)((caddr_t)saddr,
1363 rnh);
1364 if (np && np->netc_rnodes->rn_flags & RNF_ROOT)
1365 np = NULL;
1366 }
1367 }
1368 /*
1369 * If no address match, use the default if it exists.
1370 */
1371 if (np == NULL && mp->mnt_flag & MNT_DEFEXPORTED)
1372 np = &nep->ne_defexported;
1373 }
1374 return (np);
1375}