137488Smckusick /* 263180Sbostic * Copyright (c) 1989, 1993 363180Sbostic * The Regents of the University of California. All rights reserved. 465771Sbostic * (c) UNIX System Laboratories, Inc. 565771Sbostic * All or some portions of this file are derived from material licensed 665771Sbostic * to the University of California by American Telephone and Telegraph 765771Sbostic * Co. or Unix System Laboratories, Inc. and are reproduced herein with 865771Sbostic * the permission of UNIX System Laboratories, Inc. 937488Smckusick * 1044458Sbostic * %sccs.include.redist.c% 1137488Smckusick * 12*69378Smckusick * @(#)vfs_subr.c 8.23 (Berkeley) 05/10/95 1337488Smckusick */ 1437488Smckusick 1537488Smckusick /* 1637488Smckusick * External virtual filesystem routines 1737488Smckusick */ 1837488Smckusick 1951460Sbostic #include <sys/param.h> 2053829Spendry #include <sys/systm.h> 2151460Sbostic #include <sys/proc.h> 2251460Sbostic #include <sys/mount.h> 2351460Sbostic #include <sys/time.h> 2451460Sbostic #include <sys/vnode.h> 2552415Smckusick #include <sys/stat.h> 2651460Sbostic #include <sys/namei.h> 2751460Sbostic #include <sys/ucred.h> 2851460Sbostic #include <sys/buf.h> 2951460Sbostic #include <sys/errno.h> 3051460Sbostic #include <sys/malloc.h> 3165679Shibler #include <sys/domain.h> 3265679Shibler #include <sys/mbuf.h> 3337488Smckusick 3460930Smckusick #include <vm/vm.h> 3560930Smckusick #include <sys/sysctl.h> 3660930Smckusick 3755050Spendry #include <miscfs/specfs/specdev.h> 3855050Spendry 3952415Smckusick enum vtype iftovt_tab[16] = { 4052415Smckusick VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON, 4152415Smckusick VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD, 4252415Smckusick }; 4352415Smckusick int vttoif_tab[9] = { 4452415Smckusick 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, 4552415Smckusick S_IFSOCK, S_IFIFO, S_IFMT, 4652415Smckusick }; 4752415Smckusick 4837488Smckusick /* 4956608Smckusick * Insq/Remq for the vnode usage lists. 5056608Smckusick */ 5165260Smckusick #define bufinsvn(bp, dp) LIST_INSERT_HEAD(dp, bp, b_vnbufs) 5268319Scgd #define bufremvn(bp) { \ 5368319Scgd LIST_REMOVE(bp, b_vnbufs); \ 5468319Scgd (bp)->b_vnbufs.le_next = NOLIST; \ 5565260Smckusick } 5665260Smckusick TAILQ_HEAD(freelst, vnode) vnode_free_list; /* vnode free list */ 5765260Smckusick struct mntlist mountlist; /* mounted filesystem list */ 5865260Smckusick 5956608Smckusick /* 6065260Smckusick * Initialize the vnode management data structures. 6137488Smckusick */ 6268319Scgd void 6365260Smckusick vntblinit() 6437488Smckusick { 6537488Smckusick 6665260Smckusick TAILQ_INIT(&vnode_free_list); 6769325Smckusick CIRCLEQ_INIT(&mountlist); 6837488Smckusick } 6937488Smckusick 7037488Smckusick /* 7137488Smckusick * Lock a filesystem. 7237488Smckusick * Used to prevent access to it while mounting and unmounting. 7337488Smckusick */ 7468319Scgd int 7537488Smckusick vfs_lock(mp) 7637488Smckusick register struct mount *mp; 7737488Smckusick { 7837488Smckusick 7968319Scgd while (mp->mnt_flag & MNT_MLOCK) { 8041400Smckusick mp->mnt_flag |= MNT_MWAIT; 8168319Scgd tsleep((caddr_t)mp, PVFS, "vfslock", 0); 8239045Smckusick } 8341400Smckusick mp->mnt_flag |= MNT_MLOCK; 8437488Smckusick return (0); 8537488Smckusick } 8637488Smckusick 8737488Smckusick /* 8837488Smckusick * Unlock a locked filesystem. 8937488Smckusick * Panic if filesystem is not locked. 9037488Smckusick */ 9137488Smckusick void 9237488Smckusick vfs_unlock(mp) 9337488Smckusick register struct mount *mp; 9437488Smckusick { 9537488Smckusick 9641400Smckusick if ((mp->mnt_flag & MNT_MLOCK) == 0) 9741300Smckusick panic("vfs_unlock: not locked"); 9841400Smckusick mp->mnt_flag &= ~MNT_MLOCK; 9941400Smckusick if (mp->mnt_flag & MNT_MWAIT) { 10041400Smckusick mp->mnt_flag &= ~MNT_MWAIT; 10137488Smckusick wakeup((caddr_t)mp); 10237488Smckusick } 10337488Smckusick } 10437488Smckusick 10537488Smckusick /* 10641300Smckusick * Mark a mount point as busy. 10741300Smckusick * Used to synchronize access and to delay unmounting. 10841300Smckusick */ 10968319Scgd int 11041300Smckusick vfs_busy(mp) 11141300Smckusick register struct mount *mp; 11241300Smckusick { 11341300Smckusick 11468319Scgd while (mp->mnt_flag & MNT_MPBUSY) { 11541400Smckusick mp->mnt_flag |= MNT_MPWANT; 11668319Scgd tsleep((caddr_t)&mp->mnt_flag, PVFS, "vfsbusy", 0); 11741300Smckusick } 11841419Smckusick if (mp->mnt_flag & MNT_UNMOUNT) 11941419Smckusick return (1); 12041400Smckusick mp->mnt_flag |= MNT_MPBUSY; 12141300Smckusick return (0); 12241300Smckusick } 12341300Smckusick 12441300Smckusick /* 12541300Smckusick * Free a busy filesystem. 12641300Smckusick * Panic if filesystem is not busy. 12741300Smckusick */ 12868319Scgd void 12941300Smckusick vfs_unbusy(mp) 13041300Smckusick register struct mount *mp; 13141300Smckusick { 13241300Smckusick 13341400Smckusick if ((mp->mnt_flag & MNT_MPBUSY) == 0) 13441300Smckusick panic("vfs_unbusy: not busy"); 13541400Smckusick mp->mnt_flag &= ~MNT_MPBUSY; 13641400Smckusick if (mp->mnt_flag & MNT_MPWANT) { 13741400Smckusick mp->mnt_flag &= ~MNT_MPWANT; 13841400Smckusick wakeup((caddr_t)&mp->mnt_flag); 13941300Smckusick } 14041300Smckusick } 14141300Smckusick 14241300Smckusick /* 143*69378Smckusick * Lookup a filesystem type, and if found allocate and initialize 144*69378Smckusick * a mount structure for it. 145*69378Smckusick * 146*69378Smckusick * Devname is usually updated by mount(8) after booting. 147*69378Smckusick */ 148*69378Smckusick int 149*69378Smckusick vfs_rootmountalloc(fstypename, devname, mpp) 150*69378Smckusick char *fstypename; 151*69378Smckusick char *devname; 152*69378Smckusick struct mount **mpp; 153*69378Smckusick { 154*69378Smckusick struct vfsconf *vfsp; 155*69378Smckusick struct mount *mp; 156*69378Smckusick 157*69378Smckusick for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) 158*69378Smckusick if (!strcmp(vfsp->vfc_name, fstypename)) 159*69378Smckusick break; 160*69378Smckusick if (vfsp == NULL) 161*69378Smckusick return (ENODEV); 162*69378Smckusick mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); 163*69378Smckusick bzero((char *)mp, (u_long)sizeof(struct mount)); 164*69378Smckusick LIST_INIT(&mp->mnt_vnodelist); 165*69378Smckusick mp->mnt_vfc = vfsp; 166*69378Smckusick mp->mnt_op = vfsp->vfc_vfsops; 167*69378Smckusick mp->mnt_flag = MNT_RDONLY; 168*69378Smckusick mp->mnt_vnodecovered = NULLVP; 169*69378Smckusick vfsp->vfc_refcount++; 170*69378Smckusick mp->mnt_stat.f_type = vfsp->vfc_typenum; 171*69378Smckusick mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; 172*69378Smckusick strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); 173*69378Smckusick mp->mnt_stat.f_mntonname[0] = '/'; 174*69378Smckusick (void) copystr(devname, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 0); 175*69378Smckusick *mpp = mp; 176*69378Smckusick return (0); 177*69378Smckusick } 178*69378Smckusick 179*69378Smckusick /* 180*69378Smckusick * Find an appropriate filesystem to use for the root. If a filesystem 181*69378Smckusick * has not been preselected, walk through the list of known filesystems 182*69378Smckusick * trying those that have mountroot routines, and try them until one 183*69378Smckusick * works or we have tried them all. 184*69378Smckusick */ 185*69378Smckusick int 186*69378Smckusick vfs_mountroot() 187*69378Smckusick { 188*69378Smckusick struct vfsconf *vfsp; 189*69378Smckusick extern int (*mountroot)(void); 190*69378Smckusick int error; 191*69378Smckusick 192*69378Smckusick if (mountroot != NULL) 193*69378Smckusick return ((*vfsp->vfc_mountroot)()); 194*69378Smckusick for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) { 195*69378Smckusick if (vfsp->vfc_mountroot == NULL) 196*69378Smckusick continue; 197*69378Smckusick if ((error = (*vfsp->vfc_mountroot)()) == 0) 198*69378Smckusick return (0); 199*69378Smckusick printf("%s_mountroot failed: %d\n", vfsp->vfc_name, error); 200*69378Smckusick } 201*69378Smckusick return (ENODEV); 202*69378Smckusick } 203*69378Smckusick 204*69378Smckusick /* 20537488Smckusick * Lookup a mount point by filesystem identifier. 20637488Smckusick */ 20737488Smckusick struct mount * 20868659Smckusick vfs_getvfs(fsid) 20937488Smckusick fsid_t *fsid; 21037488Smckusick { 21137488Smckusick register struct mount *mp; 21237488Smckusick 21369325Smckusick for (mp = mountlist.cqh_first; mp != (void *)&mountlist; 21469325Smckusick mp = mp->mnt_list.cqe_next) { 21541400Smckusick if (mp->mnt_stat.f_fsid.val[0] == fsid->val[0] && 21665260Smckusick mp->mnt_stat.f_fsid.val[1] == fsid->val[1]) 21738288Smckusick return (mp); 21865260Smckusick } 21938288Smckusick return ((struct mount *)0); 22037488Smckusick } 22137488Smckusick 22237488Smckusick /* 22353829Spendry * Get a new unique fsid 22453829Spendry */ 22553829Spendry void 22668659Smckusick vfs_getnewfsid(mp) 22753829Spendry struct mount *mp; 22853829Spendry { 22953829Spendry static u_short xxxfs_mntid; 23053829Spendry 23153829Spendry fsid_t tfsid; 23268659Smckusick int mtype; 23353829Spendry 23468659Smckusick mtype = mp->mnt_vfc->vfc_typenum; 23565507Spendry mp->mnt_stat.f_fsid.val[0] = makedev(nblkdev + mtype, 0); 23653829Spendry mp->mnt_stat.f_fsid.val[1] = mtype; 23753829Spendry if (xxxfs_mntid == 0) 23853829Spendry ++xxxfs_mntid; 23965507Spendry tfsid.val[0] = makedev(nblkdev + mtype, xxxfs_mntid); 24053829Spendry tfsid.val[1] = mtype; 24169325Smckusick if (mountlist.cqh_first != (void *)&mountlist) { 24268659Smckusick while (vfs_getvfs(&tfsid)) { 24353936Spendry tfsid.val[0]++; 24453936Spendry xxxfs_mntid++; 24553936Spendry } 24653829Spendry } 24753829Spendry mp->mnt_stat.f_fsid.val[0] = tfsid.val[0]; 24853829Spendry } 24953829Spendry 25053829Spendry /* 25137488Smckusick * Set vnode attributes to VNOVAL 25237488Smckusick */ 25368319Scgd void 25468319Scgd vattr_null(vap) 25537488Smckusick register struct vattr *vap; 25637488Smckusick { 25737488Smckusick 25837488Smckusick vap->va_type = VNON; 25952005Smckusick vap->va_size = vap->va_bytes = VNOVAL; 26037488Smckusick vap->va_mode = vap->va_nlink = vap->va_uid = vap->va_gid = 26152005Smckusick vap->va_fsid = vap->va_fileid = 26252005Smckusick vap->va_blocksize = vap->va_rdev = 26354347Smckusick vap->va_atime.ts_sec = vap->va_atime.ts_nsec = 26454347Smckusick vap->va_mtime.ts_sec = vap->va_mtime.ts_nsec = 26554347Smckusick vap->va_ctime.ts_sec = vap->va_ctime.ts_nsec = 26638258Smckusick vap->va_flags = vap->va_gen = VNOVAL; 26758548Sbostic vap->va_vaflags = 0; 26837488Smckusick } 26938265Smckusick 27038265Smckusick /* 27139397Smckusick * Routines having to do with the management of the vnode table. 27239397Smckusick */ 27353547Sheideman extern int (**dead_vnodeop_p)(); 27439635Smckusick extern void vclean(); 27540883Smckusick long numvnodes; 27653493Sheideman extern struct vattr va_null; 27739397Smckusick 27839397Smckusick /* 27939397Smckusick * Return the next vnode from the free list. 28039397Smckusick */ 28168319Scgd int 28239397Smckusick getnewvnode(tag, mp, vops, vpp) 28339397Smckusick enum vtagtype tag; 28439397Smckusick struct mount *mp; 28553495Sheideman int (**vops)(); 28639397Smckusick struct vnode **vpp; 28739397Smckusick { 28865511Smckusick register struct vnode *vp; 28957042Smargo int s; 29039397Smckusick 29165260Smckusick if ((vnode_free_list.tqh_first == NULL && 29265260Smckusick numvnodes < 2 * desiredvnodes) || 29354347Smckusick numvnodes < desiredvnodes) { 29445118Smckusick vp = (struct vnode *)malloc((u_long)sizeof *vp, 29545118Smckusick M_VNODE, M_WAITOK); 29640883Smckusick bzero((char *)vp, sizeof *vp); 29740883Smckusick numvnodes++; 29840883Smckusick } else { 29965260Smckusick if ((vp = vnode_free_list.tqh_first) == NULL) { 30040883Smckusick tablefull("vnode"); 30140883Smckusick *vpp = 0; 30240883Smckusick return (ENFILE); 30340883Smckusick } 30440883Smckusick if (vp->v_usecount) 30540883Smckusick panic("free vnode isn't"); 30665260Smckusick TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); 30765505Smckusick /* see comment on why 0xdeadb is set at end of vgone (below) */ 30865505Smckusick vp->v_freelist.tqe_prev = (struct vnode **)0xdeadb; 30952190Smckusick vp->v_lease = NULL; 31040883Smckusick if (vp->v_type != VBAD) 31169356Spendry vgone(vp); 31257042Smargo #ifdef DIAGNOSTIC 31352006Smckusick if (vp->v_data) 31452006Smckusick panic("cleaned vnode isn't"); 31557042Smargo s = splbio(); 31657042Smargo if (vp->v_numoutput) 31757042Smargo panic("Clean vnode has pending I/O's"); 31857042Smargo splx(s); 31957042Smargo #endif 32040883Smckusick vp->v_flag = 0; 32140883Smckusick vp->v_lastr = 0; 32265745Shibler vp->v_ralen = 0; 32365745Shibler vp->v_maxra = 0; 32457042Smargo vp->v_lastw = 0; 32557042Smargo vp->v_lasta = 0; 32657042Smargo vp->v_cstart = 0; 32757042Smargo vp->v_clen = 0; 32840883Smckusick vp->v_socket = 0; 32939397Smckusick } 33039512Smckusick vp->v_type = VNON; 33139397Smckusick cache_purge(vp); 33239397Smckusick vp->v_tag = tag; 33339433Smckusick vp->v_op = vops; 33439397Smckusick insmntque(vp, mp); 33539397Smckusick *vpp = vp; 33665505Smckusick vp->v_usecount = 1; 33765260Smckusick vp->v_data = 0; 33839397Smckusick return (0); 33939397Smckusick } 34065679Shibler 34139397Smckusick /* 34239397Smckusick * Move a vnode from one mount queue to another. 34339397Smckusick */ 34468319Scgd void 34539397Smckusick insmntque(vp, mp) 34639397Smckusick register struct vnode *vp; 34739397Smckusick register struct mount *mp; 34839397Smckusick { 34939397Smckusick 35039397Smckusick /* 35139397Smckusick * Delete from old mount point vnode list, if on one. 35239397Smckusick */ 35365679Shibler if (vp->v_mount != NULL) 35465260Smckusick LIST_REMOVE(vp, v_mntvnodes); 35539397Smckusick /* 35639397Smckusick * Insert into list of vnodes for the new mount point, if available. 35739397Smckusick */ 35865260Smckusick if ((vp->v_mount = mp) == NULL) 35939397Smckusick return; 36065260Smckusick LIST_INSERT_HEAD(&mp->mnt_vnodelist, vp, v_mntvnodes); 36139397Smckusick } 36239397Smckusick 36339397Smckusick /* 36449232Smckusick * Update outstanding I/O count and do wakeup if requested. 36549232Smckusick */ 36668319Scgd void 36749232Smckusick vwakeup(bp) 36849232Smckusick register struct buf *bp; 36949232Smckusick { 37049232Smckusick register struct vnode *vp; 37149232Smckusick 37257810Smckusick bp->b_flags &= ~B_WRITEINPROG; 37349232Smckusick if (vp = bp->b_vp) { 37468319Scgd if (--vp->v_numoutput < 0) 37557042Smargo panic("vwakeup: neg numoutput"); 37649232Smckusick if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) { 37749232Smckusick if (vp->v_numoutput < 0) 37868319Scgd panic("vwakeup: neg numoutput 2"); 37949232Smckusick vp->v_flag &= ~VBWAIT; 38049232Smckusick wakeup((caddr_t)&vp->v_numoutput); 38149232Smckusick } 38249232Smckusick } 38349232Smckusick } 38449232Smckusick 38549232Smckusick /* 38649232Smckusick * Flush out and invalidate all buffers associated with a vnode. 38749232Smckusick * Called with the underlying object locked. 38849232Smckusick */ 38954442Smckusick int 39057792Smckusick vinvalbuf(vp, flags, cred, p, slpflag, slptimeo) 39149232Smckusick register struct vnode *vp; 39256459Smargo int flags; 39354442Smckusick struct ucred *cred; 39454442Smckusick struct proc *p; 39557792Smckusick int slpflag, slptimeo; 39649232Smckusick { 39749232Smckusick register struct buf *bp; 39849232Smckusick struct buf *nbp, *blist; 39954442Smckusick int s, error; 40049232Smckusick 40156459Smargo if (flags & V_SAVE) { 40254442Smckusick if (error = VOP_FSYNC(vp, cred, MNT_WAIT, p)) 40354442Smckusick return (error); 40465260Smckusick if (vp->v_dirtyblkhd.lh_first != NULL) 40554442Smckusick panic("vinvalbuf: dirty bufs"); 40654442Smckusick } 40749232Smckusick for (;;) { 40865260Smckusick if ((blist = vp->v_cleanblkhd.lh_first) && flags & V_SAVEMETA) 40956459Smargo while (blist && blist->b_lblkno < 0) 41065260Smckusick blist = blist->b_vnbufs.le_next; 41168319Scgd if (!blist && (blist = vp->v_dirtyblkhd.lh_first) && 41256608Smckusick (flags & V_SAVEMETA)) 41356459Smargo while (blist && blist->b_lblkno < 0) 41465260Smckusick blist = blist->b_vnbufs.le_next; 41556459Smargo if (!blist) 41649232Smckusick break; 41756459Smargo 41849232Smckusick for (bp = blist; bp; bp = nbp) { 41965260Smckusick nbp = bp->b_vnbufs.le_next; 42056459Smargo if (flags & V_SAVEMETA && bp->b_lblkno < 0) 42156459Smargo continue; 42249232Smckusick s = splbio(); 42349232Smckusick if (bp->b_flags & B_BUSY) { 42449232Smckusick bp->b_flags |= B_WANTED; 42557792Smckusick error = tsleep((caddr_t)bp, 42657792Smckusick slpflag | (PRIBIO + 1), "vinvalbuf", 42757792Smckusick slptimeo); 42849232Smckusick splx(s); 42957792Smckusick if (error) 43057792Smckusick return (error); 43149232Smckusick break; 43249232Smckusick } 43349232Smckusick bremfree(bp); 43449232Smckusick bp->b_flags |= B_BUSY; 43549232Smckusick splx(s); 43657792Smckusick /* 43757792Smckusick * XXX Since there are no node locks for NFS, I believe 43857792Smckusick * there is a slight chance that a delayed write will 43957792Smckusick * occur while sleeping just above, so check for it. 44057792Smckusick */ 44157792Smckusick if ((bp->b_flags & B_DELWRI) && (flags & V_SAVE)) { 44257792Smckusick (void) VOP_BWRITE(bp); 44357792Smckusick break; 44457792Smckusick } 44556459Smargo bp->b_flags |= B_INVAL; 44649232Smckusick brelse(bp); 44749232Smckusick } 44849232Smckusick } 44956608Smckusick if (!(flags & V_SAVEMETA) && 45065260Smckusick (vp->v_dirtyblkhd.lh_first || vp->v_cleanblkhd.lh_first)) 45149232Smckusick panic("vinvalbuf: flush failed"); 45254442Smckusick return (0); 45349232Smckusick } 45449232Smckusick 45549232Smckusick /* 45649232Smckusick * Associate a buffer with a vnode. 45749232Smckusick */ 45868319Scgd void 45949232Smckusick bgetvp(vp, bp) 46049232Smckusick register struct vnode *vp; 46149232Smckusick register struct buf *bp; 46249232Smckusick { 46349232Smckusick 46449232Smckusick if (bp->b_vp) 46549232Smckusick panic("bgetvp: not free"); 46649232Smckusick VHOLD(vp); 46749232Smckusick bp->b_vp = vp; 46849232Smckusick if (vp->v_type == VBLK || vp->v_type == VCHR) 46949232Smckusick bp->b_dev = vp->v_rdev; 47049232Smckusick else 47149232Smckusick bp->b_dev = NODEV; 47249232Smckusick /* 47349232Smckusick * Insert onto list for new vnode. 47449232Smckusick */ 47556608Smckusick bufinsvn(bp, &vp->v_cleanblkhd); 47649232Smckusick } 47749232Smckusick 47849232Smckusick /* 47949232Smckusick * Disassociate a buffer from a vnode. 48049232Smckusick */ 48168319Scgd void 48249232Smckusick brelvp(bp) 48349232Smckusick register struct buf *bp; 48449232Smckusick { 48549232Smckusick struct vnode *vp; 48649232Smckusick 48749232Smckusick if (bp->b_vp == (struct vnode *) 0) 48849232Smckusick panic("brelvp: NULL"); 48949232Smckusick /* 49049232Smckusick * Delete from old vnode list, if on one. 49149232Smckusick */ 49265260Smckusick if (bp->b_vnbufs.le_next != NOLIST) 49356608Smckusick bufremvn(bp); 49449232Smckusick vp = bp->b_vp; 49549232Smckusick bp->b_vp = (struct vnode *) 0; 49649232Smckusick HOLDRELE(vp); 49749232Smckusick } 49849232Smckusick 49949232Smckusick /* 50049232Smckusick * Reassign a buffer from one vnode to another. 50149232Smckusick * Used to assign file specific control information 50249232Smckusick * (indirect blocks) to the vnode to which they belong. 50349232Smckusick */ 50468319Scgd void 50549232Smckusick reassignbuf(bp, newvp) 50649232Smckusick register struct buf *bp; 50749232Smckusick register struct vnode *newvp; 50849232Smckusick { 50965260Smckusick register struct buflists *listheadp; 51049232Smckusick 51152655Smckusick if (newvp == NULL) { 51252655Smckusick printf("reassignbuf: NULL"); 51352655Smckusick return; 51452655Smckusick } 51549232Smckusick /* 51649232Smckusick * Delete from old vnode list, if on one. 51749232Smckusick */ 51865260Smckusick if (bp->b_vnbufs.le_next != NOLIST) 51956608Smckusick bufremvn(bp); 52049232Smckusick /* 52149232Smckusick * If dirty, put on list of dirty buffers; 52249232Smckusick * otherwise insert onto list of clean buffers. 52349232Smckusick */ 52449232Smckusick if (bp->b_flags & B_DELWRI) 52549232Smckusick listheadp = &newvp->v_dirtyblkhd; 52649232Smckusick else 52749232Smckusick listheadp = &newvp->v_cleanblkhd; 52856608Smckusick bufinsvn(bp, listheadp); 52949232Smckusick } 53049232Smckusick 53149232Smckusick /* 53239433Smckusick * Create a vnode for a block device. 53339433Smckusick * Used for root filesystem, argdev, and swap areas. 53439433Smckusick * Also used for memory file system special devices. 53539397Smckusick */ 53668319Scgd int 53739433Smckusick bdevvp(dev, vpp) 53839433Smckusick dev_t dev; 53939433Smckusick struct vnode **vpp; 54039433Smckusick { 54139433Smckusick register struct vnode *vp; 54239433Smckusick struct vnode *nvp; 54339433Smckusick int error; 54439433Smckusick 545*69378Smckusick if (dev == NODEV) { 546*69378Smckusick *vpp = NULLVP; 547*69378Smckusick return (ENODEV); 548*69378Smckusick } 54953547Sheideman error = getnewvnode(VT_NON, (struct mount *)0, spec_vnodeop_p, &nvp); 55039433Smckusick if (error) { 55168319Scgd *vpp = NULLVP; 55239433Smckusick return (error); 55339433Smckusick } 55439433Smckusick vp = nvp; 55539433Smckusick vp->v_type = VBLK; 55639615Smckusick if (nvp = checkalias(vp, dev, (struct mount *)0)) { 55739433Smckusick vput(vp); 55839433Smckusick vp = nvp; 55939433Smckusick } 56039433Smckusick *vpp = vp; 56139433Smckusick return (0); 56239433Smckusick } 56339433Smckusick 56439433Smckusick /* 56539433Smckusick * Check to see if the new vnode represents a special device 56639433Smckusick * for which we already have a vnode (either because of 56739433Smckusick * bdevvp() or because of a different vnode representing 56839433Smckusick * the same block device). If such an alias exists, deallocate 56939509Smckusick * the existing contents and return the aliased vnode. The 57039433Smckusick * caller is responsible for filling it with its new contents. 57139433Smckusick */ 57239433Smckusick struct vnode * 57339615Smckusick checkalias(nvp, nvp_rdev, mp) 57439433Smckusick register struct vnode *nvp; 57539615Smckusick dev_t nvp_rdev; 57639433Smckusick struct mount *mp; 57739433Smckusick { 57839433Smckusick register struct vnode *vp; 57939615Smckusick struct vnode **vpp; 58039433Smckusick 58139433Smckusick if (nvp->v_type != VBLK && nvp->v_type != VCHR) 58241400Smckusick return (NULLVP); 58339615Smckusick 58439615Smckusick vpp = &speclisth[SPECHASH(nvp_rdev)]; 58539433Smckusick loop: 58639615Smckusick for (vp = *vpp; vp; vp = vp->v_specnext) { 58739615Smckusick if (nvp_rdev != vp->v_rdev || nvp->v_type != vp->v_type) 58839433Smckusick continue; 58939615Smckusick /* 59039615Smckusick * Alias, but not in use, so flush it out. 59139615Smckusick */ 59239809Smckusick if (vp->v_usecount == 0) { 59339615Smckusick vgone(vp); 59439615Smckusick goto loop; 59539615Smckusick } 59665260Smckusick if (vget(vp, 1)) 59739633Smckusick goto loop; 59839433Smckusick break; 59939433Smckusick } 60039615Smckusick if (vp == NULL || vp->v_tag != VT_NON) { 60139615Smckusick MALLOC(nvp->v_specinfo, struct specinfo *, 60239615Smckusick sizeof(struct specinfo), M_VNODE, M_WAITOK); 60339615Smckusick nvp->v_rdev = nvp_rdev; 60439809Smckusick nvp->v_hashchain = vpp; 60539615Smckusick nvp->v_specnext = *vpp; 60642152Smckusick nvp->v_specflags = 0; 60739615Smckusick *vpp = nvp; 60840640Smckusick if (vp != NULL) { 60940640Smckusick nvp->v_flag |= VALIASED; 61040640Smckusick vp->v_flag |= VALIASED; 61140640Smckusick vput(vp); 61240640Smckusick } 61341400Smckusick return (NULLVP); 61439433Smckusick } 61539484Smckusick VOP_UNLOCK(vp); 61639484Smckusick vclean(vp, 0); 61739433Smckusick vp->v_op = nvp->v_op; 61839433Smckusick vp->v_tag = nvp->v_tag; 61939433Smckusick nvp->v_type = VNON; 62039433Smckusick insmntque(vp, mp); 62139433Smckusick return (vp); 62239433Smckusick } 62339433Smckusick 62439433Smckusick /* 62539433Smckusick * Grab a particular vnode from the free list, increment its 62639433Smckusick * reference count and lock it. The vnode lock bit is set the 62739433Smckusick * vnode is being eliminated in vgone. The process is awakened 62839433Smckusick * when the transition is completed, and an error returned to 62939433Smckusick * indicate that the vnode is no longer usable (possibly having 63039433Smckusick * been changed to a new file system type). 63139433Smckusick */ 63268319Scgd int 63365260Smckusick vget(vp, lockflag) 63439397Smckusick register struct vnode *vp; 63565260Smckusick int lockflag; 63639397Smckusick { 63739397Smckusick 63866897Smckusick /* 63966897Smckusick * If the vnode is in the process of being cleaned out for 64066897Smckusick * another use, we wait for the cleaning to finish and then 64166897Smckusick * return failure. Cleaning is determined either by checking 64266897Smckusick * that the VXLOCK flag is set, or that the use count is 64366897Smckusick * zero with the back pointer set to show that it has been 64466897Smckusick * removed from the free list by getnewvnode. The VXLOCK 64566897Smckusick * flag may not have been set yet because vclean is blocked in 64666897Smckusick * the VOP_LOCK call waiting for the VOP_INACTIVE to complete. 64766897Smckusick */ 64866897Smckusick if ((vp->v_flag & VXLOCK) || 64966897Smckusick (vp->v_usecount == 0 && 65066897Smckusick vp->v_freelist.tqe_prev == (struct vnode **)0xdeadb)) { 65139433Smckusick vp->v_flag |= VXWANT; 65268319Scgd tsleep((caddr_t)vp, PINOD, "vget", 0); 65339433Smckusick return (1); 65439433Smckusick } 65566897Smckusick if (vp->v_usecount == 0) 65665260Smckusick TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); 65759450Smckusick vp->v_usecount++; 65865260Smckusick if (lockflag) 65965260Smckusick VOP_LOCK(vp); 66039433Smckusick return (0); 66139397Smckusick } 66239397Smckusick 66339397Smckusick /* 66439397Smckusick * Vnode reference, just increment the count 66539397Smckusick */ 66668319Scgd void 66768319Scgd vref(vp) 66839397Smckusick struct vnode *vp; 66939397Smckusick { 67039397Smckusick 67159450Smckusick if (vp->v_usecount <= 0) 67259450Smckusick panic("vref used where vget required"); 67339809Smckusick vp->v_usecount++; 67439397Smckusick } 67539397Smckusick 67639397Smckusick /* 67739397Smckusick * vput(), just unlock and vrele() 67839397Smckusick */ 67968319Scgd void 68068319Scgd vput(vp) 68139397Smckusick register struct vnode *vp; 68239397Smckusick { 68352416Storek 68439397Smckusick VOP_UNLOCK(vp); 68539397Smckusick vrele(vp); 68639397Smckusick } 68739397Smckusick 68839397Smckusick /* 68939397Smckusick * Vnode release. 69039397Smckusick * If count drops to zero, call inactive routine and return to freelist. 69139397Smckusick */ 69268319Scgd void 69368319Scgd vrele(vp) 69439397Smckusick register struct vnode *vp; 69539397Smckusick { 69639397Smckusick 69750109Smckusick #ifdef DIAGNOSTIC 69839397Smckusick if (vp == NULL) 69939433Smckusick panic("vrele: null vp"); 70050109Smckusick #endif 70139809Smckusick vp->v_usecount--; 70239809Smckusick if (vp->v_usecount > 0) 70339397Smckusick return; 70450109Smckusick #ifdef DIAGNOSTIC 70550109Smckusick if (vp->v_usecount != 0 || vp->v_writecount != 0) { 70650109Smckusick vprint("vrele: bad ref count", vp); 70750109Smckusick panic("vrele: ref cnt"); 70850109Smckusick } 70950109Smckusick #endif 71055468Smckusick /* 71155468Smckusick * insert at tail of LRU list 71255468Smckusick */ 71365260Smckusick TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); 71454442Smckusick VOP_INACTIVE(vp); 71539397Smckusick } 71639433Smckusick 71739433Smckusick /* 71839809Smckusick * Page or buffer structure gets a reference. 71939809Smckusick */ 72068319Scgd void 72168319Scgd vhold(vp) 72239809Smckusick register struct vnode *vp; 72339809Smckusick { 72439809Smckusick 72539809Smckusick vp->v_holdcnt++; 72639809Smckusick } 72739809Smckusick 72839809Smckusick /* 72939809Smckusick * Page or buffer structure frees a reference. 73039809Smckusick */ 73168319Scgd void 73268319Scgd holdrele(vp) 73339809Smckusick register struct vnode *vp; 73439809Smckusick { 73539809Smckusick 73639809Smckusick if (vp->v_holdcnt <= 0) 73739809Smckusick panic("holdrele: holdcnt"); 73839809Smckusick vp->v_holdcnt--; 73939809Smckusick } 74039809Smckusick 74139809Smckusick /* 74239509Smckusick * Remove any vnodes in the vnode table belonging to mount point mp. 74339509Smckusick * 74439509Smckusick * If MNT_NOFORCE is specified, there should not be any active ones, 74539509Smckusick * return error if any are found (nb: this is a user error, not a 74639509Smckusick * system error). If MNT_FORCE is specified, detach any active vnodes 74739509Smckusick * that are found. 74839509Smckusick */ 74965679Shibler #ifdef DIAGNOSTIC 75060930Smckusick int busyprt = 0; /* print out busy vnodes */ 75160930Smckusick struct ctldebug debug1 = { "busyprt", &busyprt }; 75265679Shibler #endif 75339509Smckusick 75468319Scgd int 75539509Smckusick vflush(mp, skipvp, flags) 75639509Smckusick struct mount *mp; 75739509Smckusick struct vnode *skipvp; 75839509Smckusick int flags; 75939509Smckusick { 76039509Smckusick register struct vnode *vp, *nvp; 76139509Smckusick int busy = 0; 76239509Smckusick 76341400Smckusick if ((mp->mnt_flag & MNT_MPBUSY) == 0) 76441300Smckusick panic("vflush: not busy"); 76541421Smckusick loop: 76665260Smckusick for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) { 76741421Smckusick if (vp->v_mount != mp) 76841421Smckusick goto loop; 76965260Smckusick nvp = vp->v_mntvnodes.le_next; 77039509Smckusick /* 77139509Smckusick * Skip over a selected vnode. 77239509Smckusick */ 77339509Smckusick if (vp == skipvp) 77439509Smckusick continue; 77539509Smckusick /* 77641300Smckusick * Skip over a vnodes marked VSYSTEM. 77741300Smckusick */ 77841300Smckusick if ((flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM)) 77941300Smckusick continue; 78041300Smckusick /* 78157040Smckusick * If WRITECLOSE is set, only flush out regular file 78257040Smckusick * vnodes open for writing. 78357040Smckusick */ 78457040Smckusick if ((flags & WRITECLOSE) && 78557040Smckusick (vp->v_writecount == 0 || vp->v_type != VREG)) 78657040Smckusick continue; 78757040Smckusick /* 78839809Smckusick * With v_usecount == 0, all we need to do is clear 78939509Smckusick * out the vnode data structures and we are done. 79039509Smckusick */ 79139809Smckusick if (vp->v_usecount == 0) { 79269356Spendry vgone(vp); 79339509Smckusick continue; 79439509Smckusick } 79539509Smckusick /* 79657040Smckusick * If FORCECLOSE is set, forcibly close the vnode. 79739509Smckusick * For block or character devices, revert to an 79839509Smckusick * anonymous device. For all other files, just kill them. 79939509Smckusick */ 80041300Smckusick if (flags & FORCECLOSE) { 80139509Smckusick if (vp->v_type != VBLK && vp->v_type != VCHR) { 80269356Spendry vgone(vp); 80339509Smckusick } else { 80439509Smckusick vclean(vp, 0); 80553547Sheideman vp->v_op = spec_vnodeop_p; 80639509Smckusick insmntque(vp, (struct mount *)0); 80739509Smckusick } 80839509Smckusick continue; 80939509Smckusick } 81065679Shibler #ifdef DIAGNOSTIC 81139509Smckusick if (busyprt) 81239667Smckusick vprint("vflush: busy vnode", vp); 81365679Shibler #endif 81439509Smckusick busy++; 81539509Smckusick } 81639509Smckusick if (busy) 81739509Smckusick return (EBUSY); 81839509Smckusick return (0); 81939509Smckusick } 82039509Smckusick 82139509Smckusick /* 82239433Smckusick * Disassociate the underlying file system from a vnode. 82339433Smckusick */ 82454347Smckusick void 82554347Smckusick vclean(vp, flags) 82639433Smckusick register struct vnode *vp; 82745118Smckusick int flags; 82839433Smckusick { 82939484Smckusick int active; 83039433Smckusick 83139484Smckusick /* 83239484Smckusick * Check to see if the vnode is in use. 83339667Smckusick * If so we have to reference it before we clean it out 83439667Smckusick * so that its count cannot fall to zero and generate a 83539667Smckusick * race against ourselves to recycle it. 83639484Smckusick */ 83739809Smckusick if (active = vp->v_usecount) 83839484Smckusick VREF(vp); 83939484Smckusick /* 84056805Smckusick * Even if the count is zero, the VOP_INACTIVE routine may still 84156805Smckusick * have the object locked while it cleans it out. The VOP_LOCK 84256805Smckusick * ensures that the VOP_INACTIVE routine is done with its work. 84356805Smckusick * For active vnodes, it ensures that no other activity can 84456805Smckusick * occur while the underlying object is being cleaned out. 84556805Smckusick */ 84656805Smckusick VOP_LOCK(vp); 84756805Smckusick /* 84839484Smckusick * Prevent the vnode from being recycled or 84939484Smckusick * brought into use while we clean it out. 85039484Smckusick */ 85139667Smckusick if (vp->v_flag & VXLOCK) 85239667Smckusick panic("vclean: deadlock"); 85339433Smckusick vp->v_flag |= VXLOCK; 85439433Smckusick /* 85556805Smckusick * Clean out any buffers associated with the vnode. 85639667Smckusick */ 85741300Smckusick if (flags & DOCLOSE) 85857792Smckusick vinvalbuf(vp, V_SAVE, NOCRED, NULL, 0, 0); 85939667Smckusick /* 86056805Smckusick * Any other processes trying to obtain this lock must first 86156805Smckusick * wait for VXLOCK to clear, then call the new lock operation. 86239433Smckusick */ 86356805Smckusick VOP_UNLOCK(vp); 86439433Smckusick /* 86556805Smckusick * If purging an active vnode, it must be closed and 86656805Smckusick * deactivated before being reclaimed. 86739433Smckusick */ 86839484Smckusick if (active) { 86956805Smckusick if (flags & DOCLOSE) 87056805Smckusick VOP_CLOSE(vp, IO_NDELAY, NOCRED, NULL); 87156805Smckusick VOP_INACTIVE(vp); 87239433Smckusick } 87339433Smckusick /* 87439433Smckusick * Reclaim the vnode. 87539433Smckusick */ 87656805Smckusick if (VOP_RECLAIM(vp)) 87739433Smckusick panic("vclean: cannot reclaim"); 87839484Smckusick if (active) 87939484Smckusick vrele(vp); 88068784Smckusick cache_purge(vp); 88153580Sheideman 88239433Smckusick /* 88356805Smckusick * Done with purge, notify sleepers of the grim news. 88439433Smckusick */ 88556805Smckusick vp->v_op = dead_vnodeop_p; 88656805Smckusick vp->v_tag = VT_NON; 88739433Smckusick vp->v_flag &= ~VXLOCK; 88839433Smckusick if (vp->v_flag & VXWANT) { 88939433Smckusick vp->v_flag &= ~VXWANT; 89039433Smckusick wakeup((caddr_t)vp); 89139433Smckusick } 89239433Smckusick } 89339433Smckusick 89439433Smckusick /* 89539633Smckusick * Eliminate all activity associated with the requested vnode 89639633Smckusick * and with all vnodes aliased to the requested vnode. 89739633Smckusick */ 89868424Smckusick int 89968424Smckusick vop_revoke(ap) 90068424Smckusick struct vop_revoke_args /* { 90168424Smckusick struct vnode *a_vp; 90268424Smckusick int a_flags; 90368424Smckusick } */ *ap; 90439633Smckusick { 90568424Smckusick register struct vnode *vp, *vq; 90639633Smckusick 90768424Smckusick vp = ap->a_vp; 90868424Smckusick if ((ap->a_flags & REVOKEALL) && (vp->v_flag & VALIASED)) { 90940665Smckusick /* 91040665Smckusick * If a vgone (or vclean) is already in progress, 91140665Smckusick * wait until it is done and return. 91240665Smckusick */ 91340665Smckusick if (vp->v_flag & VXLOCK) { 91440665Smckusick vp->v_flag |= VXWANT; 91568424Smckusick tsleep((caddr_t)vp, PINOD, "vop_revokeall", 0); 91668424Smckusick return (0); 91739633Smckusick } 91840665Smckusick /* 91940665Smckusick * Ensure that vp will not be vgone'd while we 92040665Smckusick * are eliminating its aliases. 92140665Smckusick */ 92240665Smckusick vp->v_flag |= VXLOCK; 92340665Smckusick while (vp->v_flag & VALIASED) { 92440665Smckusick for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) { 92540665Smckusick if (vq->v_rdev != vp->v_rdev || 92640665Smckusick vq->v_type != vp->v_type || vp == vq) 92740665Smckusick continue; 92840665Smckusick vgone(vq); 92940665Smckusick break; 93040665Smckusick } 93140665Smckusick } 93240665Smckusick /* 93340665Smckusick * Remove the lock so that vgone below will 93440665Smckusick * really eliminate the vnode after which time 93540665Smckusick * vgone will awaken any sleepers. 93640665Smckusick */ 93740665Smckusick vp->v_flag &= ~VXLOCK; 93839633Smckusick } 93939633Smckusick vgone(vp); 94068424Smckusick return (0); 94139633Smckusick } 94239633Smckusick 94339633Smckusick /* 94439433Smckusick * Eliminate all activity associated with a vnode 94539433Smckusick * in preparation for reuse. 94639433Smckusick */ 94768319Scgd void 94868319Scgd vgone(vp) 94939433Smckusick register struct vnode *vp; 95039433Smckusick { 95139809Smckusick register struct vnode *vq; 95239615Smckusick struct vnode *vx; 95339433Smckusick 95439433Smckusick /* 95540548Smckusick * If a vgone (or vclean) is already in progress, 95640548Smckusick * wait until it is done and return. 95740548Smckusick */ 95840548Smckusick if (vp->v_flag & VXLOCK) { 95940548Smckusick vp->v_flag |= VXWANT; 96068319Scgd tsleep((caddr_t)vp, PINOD, "vgone", 0); 96140548Smckusick return; 96240548Smckusick } 96340548Smckusick /* 96439433Smckusick * Clean out the filesystem specific data. 96539433Smckusick */ 96641300Smckusick vclean(vp, DOCLOSE); 96739433Smckusick /* 96839433Smckusick * Delete from old mount point vnode list, if on one. 96939433Smckusick */ 97065260Smckusick if (vp->v_mount != NULL) { 97165260Smckusick LIST_REMOVE(vp, v_mntvnodes); 97252311Smckusick vp->v_mount = NULL; 97339433Smckusick } 97439433Smckusick /* 97568592Smckusick * If special device, remove it from special device alias list 97668592Smckusick * if it is on one. 97739433Smckusick */ 97868592Smckusick if ((vp->v_type == VBLK || vp->v_type == VCHR) && vp->v_specinfo != 0) { 97939809Smckusick if (*vp->v_hashchain == vp) { 98039809Smckusick *vp->v_hashchain = vp->v_specnext; 98139433Smckusick } else { 98239809Smckusick for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) { 98339615Smckusick if (vq->v_specnext != vp) 98439433Smckusick continue; 98539615Smckusick vq->v_specnext = vp->v_specnext; 98639433Smckusick break; 98739433Smckusick } 98839615Smckusick if (vq == NULL) 98939433Smckusick panic("missing bdev"); 99039433Smckusick } 99139615Smckusick if (vp->v_flag & VALIASED) { 99252416Storek vx = NULL; 99339809Smckusick for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) { 99440108Smckusick if (vq->v_rdev != vp->v_rdev || 99540108Smckusick vq->v_type != vp->v_type) 99639615Smckusick continue; 99752416Storek if (vx) 99852416Storek break; 99939615Smckusick vx = vq; 100039615Smckusick } 100152416Storek if (vx == NULL) 100239615Smckusick panic("missing alias"); 100352416Storek if (vq == NULL) 100439615Smckusick vx->v_flag &= ~VALIASED; 100539615Smckusick vp->v_flag &= ~VALIASED; 100639615Smckusick } 100739615Smckusick FREE(vp->v_specinfo, M_VNODE); 100839615Smckusick vp->v_specinfo = NULL; 100939433Smckusick } 101039433Smckusick /* 101156932Smckusick * If it is on the freelist and not already at the head, 101265505Smckusick * move it to the head of the list. The test of the back 101365505Smckusick * pointer and the reference count of zero is because 101465505Smckusick * it will be removed from the free list by getnewvnode, 101565505Smckusick * but will not have its reference count incremented until 101665505Smckusick * after calling vgone. If the reference count were 101765505Smckusick * incremented first, vgone would (incorrectly) try to 101865505Smckusick * close the previous instance of the underlying object. 101965505Smckusick * So, the back pointer is explicitly set to `0xdeadb' in 102065505Smckusick * getnewvnode after removing it from the freelist to ensure 102165505Smckusick * that we do not try to move it here. 102239433Smckusick */ 102365505Smckusick if (vp->v_usecount == 0 && 102465505Smckusick vp->v_freelist.tqe_prev != (struct vnode **)0xdeadb && 102565505Smckusick vnode_free_list.tqh_first != vp) { 102665260Smckusick TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); 102765260Smckusick TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); 102839433Smckusick } 102939484Smckusick vp->v_type = VBAD; 103039433Smckusick } 103139633Smckusick 103239633Smckusick /* 103339821Smckusick * Lookup a vnode by device number. 103439821Smckusick */ 103568319Scgd int 103639821Smckusick vfinddev(dev, type, vpp) 103739821Smckusick dev_t dev; 103839821Smckusick enum vtype type; 103939821Smckusick struct vnode **vpp; 104039821Smckusick { 104139821Smckusick register struct vnode *vp; 104239821Smckusick 104339821Smckusick for (vp = speclisth[SPECHASH(dev)]; vp; vp = vp->v_specnext) { 104439821Smckusick if (dev != vp->v_rdev || type != vp->v_type) 104539821Smckusick continue; 104639821Smckusick *vpp = vp; 104759484Smckusick return (1); 104839821Smckusick } 104959484Smckusick return (0); 105039821Smckusick } 105139821Smckusick 105239821Smckusick /* 105339633Smckusick * Calculate the total number of references to a special device. 105439633Smckusick */ 105568319Scgd int 105639633Smckusick vcount(vp) 105739633Smckusick register struct vnode *vp; 105839633Smckusick { 105966742Smckusick register struct vnode *vq, *vnext; 106039633Smckusick int count; 106139633Smckusick 106266742Smckusick loop: 106339633Smckusick if ((vp->v_flag & VALIASED) == 0) 106439809Smckusick return (vp->v_usecount); 106566742Smckusick for (count = 0, vq = *vp->v_hashchain; vq; vq = vnext) { 106666742Smckusick vnext = vq->v_specnext; 106740108Smckusick if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type) 106839633Smckusick continue; 106939633Smckusick /* 107039633Smckusick * Alias, but not in use, so flush it out. 107139633Smckusick */ 107266742Smckusick if (vq->v_usecount == 0 && vq != vp) { 107339633Smckusick vgone(vq); 107439633Smckusick goto loop; 107539633Smckusick } 107639809Smckusick count += vq->v_usecount; 107739633Smckusick } 107839633Smckusick return (count); 107939633Smckusick } 108039667Smckusick 108139667Smckusick /* 108239667Smckusick * Print out a description of a vnode. 108339667Smckusick */ 108439667Smckusick static char *typename[] = 108540286Smckusick { "VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD" }; 108639667Smckusick 108768171Scgd void 108839667Smckusick vprint(label, vp) 108939667Smckusick char *label; 109039667Smckusick register struct vnode *vp; 109139667Smckusick { 109239913Smckusick char buf[64]; 109339667Smckusick 109439667Smckusick if (label != NULL) 109539667Smckusick printf("%s: ", label); 109650109Smckusick printf("type %s, usecount %d, writecount %d, refcount %d,", 109750109Smckusick typename[vp->v_type], vp->v_usecount, vp->v_writecount, 109850109Smckusick vp->v_holdcnt); 109939913Smckusick buf[0] = '\0'; 110039913Smckusick if (vp->v_flag & VROOT) 110139913Smckusick strcat(buf, "|VROOT"); 110239913Smckusick if (vp->v_flag & VTEXT) 110339913Smckusick strcat(buf, "|VTEXT"); 110441300Smckusick if (vp->v_flag & VSYSTEM) 110541300Smckusick strcat(buf, "|VSYSTEM"); 110641300Smckusick if (vp->v_flag & VXLOCK) 110741300Smckusick strcat(buf, "|VXLOCK"); 110841300Smckusick if (vp->v_flag & VXWANT) 110941300Smckusick strcat(buf, "|VXWANT"); 111041300Smckusick if (vp->v_flag & VBWAIT) 111141300Smckusick strcat(buf, "|VBWAIT"); 111239913Smckusick if (vp->v_flag & VALIASED) 111339913Smckusick strcat(buf, "|VALIASED"); 111439913Smckusick if (buf[0] != '\0') 111539913Smckusick printf(" flags (%s)", &buf[1]); 111665260Smckusick if (vp->v_data == NULL) { 111765260Smckusick printf("\n"); 111865260Smckusick } else { 111965260Smckusick printf("\n\t"); 112065260Smckusick VOP_PRINT(vp); 112165260Smckusick } 112239667Smckusick } 112341110Smarc 112449691Smckusick #ifdef DEBUG 112549691Smckusick /* 112649691Smckusick * List all of the locked vnodes in the system. 112749691Smckusick * Called when debugging the kernel. 112849691Smckusick */ 112968319Scgd void 113049691Smckusick printlockedvnodes() 113149691Smckusick { 113249691Smckusick register struct mount *mp; 113349691Smckusick register struct vnode *vp; 113449691Smckusick 113549691Smckusick printf("Locked vnodes\n"); 113669325Smckusick for (mp = mountlist.cqh_first; mp != (void *)&mountlist; 113769325Smckusick mp = mp->mnt_list.cqe_next) { 113865260Smckusick for (vp = mp->mnt_vnodelist.lh_first; 113965260Smckusick vp != NULL; 114069325Smckusick vp = vp->v_mntvnodes.le_next) { 114149691Smckusick if (VOP_ISLOCKED(vp)) 114249691Smckusick vprint((char *)0, vp); 114369325Smckusick } 114465260Smckusick } 114549691Smckusick } 114649691Smckusick #endif 114749691Smckusick 114868659Smckusick /* 114968659Smckusick * Top level filesystem related information gathering. 115068659Smckusick */ 115168659Smckusick int 115268659Smckusick vfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 115368659Smckusick int *name; 115468659Smckusick u_int namelen; 115568659Smckusick void *oldp; 115668659Smckusick size_t *oldlenp; 115768659Smckusick void *newp; 115868659Smckusick size_t newlen; 115968659Smckusick struct proc *p; 116068659Smckusick { 116168659Smckusick struct ctldebug *cdp; 116268659Smckusick struct vfsconf *vfsp; 116368659Smckusick 116468659Smckusick /* all sysctl names at this level are at least name and field */ 116568659Smckusick if (namelen < 2) 116668659Smckusick return (ENOTDIR); /* overloaded */ 116768659Smckusick if (name[0] != VFS_GENERIC) { 116868659Smckusick for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) 116968659Smckusick if (vfsp->vfc_typenum == name[0]) 117068659Smckusick break; 117168659Smckusick if (vfsp == NULL) 117268659Smckusick return (EOPNOTSUPP); 117368659Smckusick return ((*vfsp->vfc_vfsops->vfs_sysctl)(&name[1], namelen - 1, 117468659Smckusick oldp, oldlenp, newp, newlen, p)); 117568659Smckusick } 117668659Smckusick switch (name[1]) { 117768659Smckusick case VFS_MAXTYPENUM: 117868659Smckusick return (sysctl_rdint(oldp, oldlenp, newp, maxvfsconf)); 117968659Smckusick case VFS_CONF: 118068659Smckusick if (namelen < 3) 118168659Smckusick return (ENOTDIR); /* overloaded */ 118268659Smckusick for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) 118368659Smckusick if (vfsp->vfc_typenum == name[2]) 118468659Smckusick break; 118568659Smckusick if (vfsp == NULL) 118668659Smckusick return (EOPNOTSUPP); 118768659Smckusick return (sysctl_rdstruct(oldp, oldlenp, newp, vfsp, 118868659Smckusick sizeof(struct vfsconf))); 118968659Smckusick } 119068659Smckusick return (EOPNOTSUPP); 119168659Smckusick } 119268659Smckusick 119341110Smarc int kinfo_vdebug = 1; 119441110Smarc int kinfo_vgetfailed; 119541110Smarc #define KINFO_VNODESLOP 10 119641110Smarc /* 119757841Smckusick * Dump vnode list (via sysctl). 119841110Smarc * Copyout address of vnode followed by vnode. 119941110Smarc */ 120045118Smckusick /* ARGSUSED */ 120168319Scgd int 120257841Smckusick sysctl_vnode(where, sizep) 120341110Smarc char *where; 120458465Sbostic size_t *sizep; 120541110Smarc { 120665260Smckusick register struct mount *mp, *nmp; 120741110Smarc struct vnode *vp; 120841110Smarc register char *bp = where, *savebp; 120953818Smckusick char *ewhere; 121041110Smarc int error; 121141110Smarc 121241110Smarc #define VPTRSZ sizeof (struct vnode *) 121341110Smarc #define VNODESZ sizeof (struct vnode) 121441110Smarc if (where == NULL) { 121557841Smckusick *sizep = (numvnodes + KINFO_VNODESLOP) * (VPTRSZ + VNODESZ); 121641110Smarc return (0); 121741110Smarc } 121857841Smckusick ewhere = where + *sizep; 121941110Smarc 122069325Smckusick for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { 122169325Smckusick nmp = mp->mnt_list.cqe_next; 122265260Smckusick if (vfs_busy(mp)) 122341300Smckusick continue; 122441110Smarc savebp = bp; 122541110Smarc again: 122665260Smckusick for (vp = mp->mnt_vnodelist.lh_first; 122765260Smckusick vp != NULL; 122865260Smckusick vp = vp->v_mntvnodes.le_next) { 122941422Smckusick /* 123041422Smckusick * Check that the vp is still associated with 123141422Smckusick * this filesystem. RACE: could have been 123241422Smckusick * recycled onto the same filesystem. 123341422Smckusick */ 123441421Smckusick if (vp->v_mount != mp) { 123541421Smckusick if (kinfo_vdebug) 123641421Smckusick printf("kinfo: vp changed\n"); 123741421Smckusick bp = savebp; 123841421Smckusick goto again; 123941421Smckusick } 124057841Smckusick if (bp + VPTRSZ + VNODESZ > ewhere) { 124157841Smckusick *sizep = bp - where; 124257841Smckusick return (ENOMEM); 124357841Smckusick } 124457841Smckusick if ((error = copyout((caddr_t)&vp, bp, VPTRSZ)) || 124557841Smckusick (error = copyout((caddr_t)vp, bp + VPTRSZ, VNODESZ))) 124641110Smarc return (error); 124741110Smarc bp += VPTRSZ + VNODESZ; 124841110Smarc } 124965260Smckusick vfs_unbusy(mp); 125065260Smckusick } 125141110Smarc 125257841Smckusick *sizep = bp - where; 125341110Smarc return (0); 125441110Smarc } 125565679Shibler 125665679Shibler /* 125765679Shibler * Check to see if a filesystem is mounted on a block device. 125865679Shibler */ 125965679Shibler int 126065679Shibler vfs_mountedon(vp) 126165679Shibler register struct vnode *vp; 126265679Shibler { 126365679Shibler register struct vnode *vq; 126465679Shibler 126565679Shibler if (vp->v_specflags & SI_MOUNTEDON) 126665679Shibler return (EBUSY); 126765679Shibler if (vp->v_flag & VALIASED) { 126865679Shibler for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) { 126965679Shibler if (vq->v_rdev != vp->v_rdev || 127065679Shibler vq->v_type != vp->v_type) 127165679Shibler continue; 127265679Shibler if (vq->v_specflags & SI_MOUNTEDON) 127365679Shibler return (EBUSY); 127465679Shibler } 127565679Shibler } 127665679Shibler return (0); 127765679Shibler } 127865679Shibler 127965679Shibler /* 128069325Smckusick * Unmount all filesystems. The list is traversed in reverse order 128169325Smckusick * of mounting to avoid dependencies. 128269325Smckusick */ 128369325Smckusick void 128469325Smckusick vfs_unmountall() 128569325Smckusick { 128669325Smckusick struct mount *mp, *nmp; 128769325Smckusick 128869325Smckusick for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) { 128969325Smckusick nmp = mp->mnt_list.cqe_prev; 129069325Smckusick (void) dounmount(mp, MNT_FORCE, &proc0); 129169325Smckusick } 129269325Smckusick } 129369325Smckusick 129469325Smckusick /* 129565679Shibler * Build hash lists of net addresses and hang them off the mount point. 129665679Shibler * Called by ufs_mount() to set up the lists of export addresses. 129765679Shibler */ 129865679Shibler static int 129965679Shibler vfs_hang_addrlist(mp, nep, argp) 130065679Shibler struct mount *mp; 130165679Shibler struct netexport *nep; 130265679Shibler struct export_args *argp; 130365679Shibler { 130465679Shibler register struct netcred *np; 130565679Shibler register struct radix_node_head *rnh; 130665679Shibler register int i; 130765679Shibler struct radix_node *rn; 130865679Shibler struct sockaddr *saddr, *smask = 0; 130965679Shibler struct domain *dom; 131065679Shibler int error; 131165679Shibler 131265679Shibler if (argp->ex_addrlen == 0) { 131365679Shibler if (mp->mnt_flag & MNT_DEFEXPORTED) 131465679Shibler return (EPERM); 131565679Shibler np = &nep->ne_defexported; 131665679Shibler np->netc_exflags = argp->ex_flags; 131765679Shibler np->netc_anon = argp->ex_anon; 131865679Shibler np->netc_anon.cr_ref = 1; 131965679Shibler mp->mnt_flag |= MNT_DEFEXPORTED; 132065679Shibler return (0); 132165679Shibler } 132265679Shibler i = sizeof(struct netcred) + argp->ex_addrlen + argp->ex_masklen; 132365679Shibler np = (struct netcred *)malloc(i, M_NETADDR, M_WAITOK); 132465679Shibler bzero((caddr_t)np, i); 132565679Shibler saddr = (struct sockaddr *)(np + 1); 132665679Shibler if (error = copyin(argp->ex_addr, (caddr_t)saddr, argp->ex_addrlen)) 132765679Shibler goto out; 132865679Shibler if (saddr->sa_len > argp->ex_addrlen) 132965679Shibler saddr->sa_len = argp->ex_addrlen; 133065679Shibler if (argp->ex_masklen) { 133165679Shibler smask = (struct sockaddr *)((caddr_t)saddr + argp->ex_addrlen); 133265679Shibler error = copyin(argp->ex_addr, (caddr_t)smask, argp->ex_masklen); 133365679Shibler if (error) 133465679Shibler goto out; 133565679Shibler if (smask->sa_len > argp->ex_masklen) 133665679Shibler smask->sa_len = argp->ex_masklen; 133765679Shibler } 133865679Shibler i = saddr->sa_family; 133965679Shibler if ((rnh = nep->ne_rtable[i]) == 0) { 134065679Shibler /* 134165679Shibler * Seems silly to initialize every AF when most are not 134265679Shibler * used, do so on demand here 134365679Shibler */ 134465679Shibler for (dom = domains; dom; dom = dom->dom_next) 134565679Shibler if (dom->dom_family == i && dom->dom_rtattach) { 134665679Shibler dom->dom_rtattach((void **)&nep->ne_rtable[i], 134765679Shibler dom->dom_rtoffset); 134865679Shibler break; 134965679Shibler } 135065679Shibler if ((rnh = nep->ne_rtable[i]) == 0) { 135165679Shibler error = ENOBUFS; 135265679Shibler goto out; 135365679Shibler } 135465679Shibler } 135565679Shibler rn = (*rnh->rnh_addaddr)((caddr_t)saddr, (caddr_t)smask, rnh, 135665679Shibler np->netc_rnodes); 135769140Smckusick if (rn == 0) { 135869140Smckusick /* 135969140Smckusick * One of the reasons that rnh_addaddr may fail is that 136069140Smckusick * the entry already exists. To check for this case, we 136169140Smckusick * look up the entry to see if it is there. If so, we 136269140Smckusick * do not need to make a new entry but do return success. 136369140Smckusick */ 136469140Smckusick free(np, M_NETADDR); 136569140Smckusick rn = (*rnh->rnh_matchaddr)((caddr_t)saddr, rnh); 136669140Smckusick if (rn != 0 && (rn->rn_flags & RNF_ROOT) == 0 && 136769140Smckusick ((struct netcred *)rn)->netc_exflags == argp->ex_flags && 136869140Smckusick !bcmp((caddr_t)&((struct netcred *)rn)->netc_anon, 136969140Smckusick (caddr_t)&argp->ex_anon, sizeof(struct ucred))) 137069140Smckusick return (0); 137169140Smckusick return (EPERM); 137265679Shibler } 137365679Shibler np->netc_exflags = argp->ex_flags; 137465679Shibler np->netc_anon = argp->ex_anon; 137565679Shibler np->netc_anon.cr_ref = 1; 137665679Shibler return (0); 137765679Shibler out: 137865679Shibler free(np, M_NETADDR); 137965679Shibler return (error); 138065679Shibler } 138165679Shibler 138265679Shibler /* ARGSUSED */ 138365679Shibler static int 138465679Shibler vfs_free_netcred(rn, w) 138565679Shibler struct radix_node *rn; 138665679Shibler caddr_t w; 138765679Shibler { 138865679Shibler register struct radix_node_head *rnh = (struct radix_node_head *)w; 138965679Shibler 139065679Shibler (*rnh->rnh_deladdr)(rn->rn_key, rn->rn_mask, rnh); 139165679Shibler free((caddr_t)rn, M_NETADDR); 139265679Shibler return (0); 139365679Shibler } 139468319Scgd 139565679Shibler /* 139665679Shibler * Free the net address hash lists that are hanging off the mount points. 139765679Shibler */ 139865679Shibler static void 139965679Shibler vfs_free_addrlist(nep) 140065679Shibler struct netexport *nep; 140165679Shibler { 140265679Shibler register int i; 140365679Shibler register struct radix_node_head *rnh; 140465679Shibler 140565679Shibler for (i = 0; i <= AF_MAX; i++) 140665679Shibler if (rnh = nep->ne_rtable[i]) { 140765679Shibler (*rnh->rnh_walktree)(rnh, vfs_free_netcred, 140865679Shibler (caddr_t)rnh); 140965679Shibler free((caddr_t)rnh, M_RTABLE); 141065679Shibler nep->ne_rtable[i] = 0; 141165679Shibler } 141265679Shibler } 141365679Shibler 141465679Shibler int 141565679Shibler vfs_export(mp, nep, argp) 141665679Shibler struct mount *mp; 141765679Shibler struct netexport *nep; 141865679Shibler struct export_args *argp; 141965679Shibler { 142065679Shibler int error; 142165679Shibler 142265679Shibler if (argp->ex_flags & MNT_DELEXPORT) { 142365679Shibler vfs_free_addrlist(nep); 142465679Shibler mp->mnt_flag &= ~(MNT_EXPORTED | MNT_DEFEXPORTED); 142565679Shibler } 142665679Shibler if (argp->ex_flags & MNT_EXPORTED) { 142765679Shibler if (error = vfs_hang_addrlist(mp, nep, argp)) 142865679Shibler return (error); 142965679Shibler mp->mnt_flag |= MNT_EXPORTED; 143065679Shibler } 143165679Shibler return (0); 143265679Shibler } 143365679Shibler 143465679Shibler struct netcred * 143565679Shibler vfs_export_lookup(mp, nep, nam) 143665679Shibler register struct mount *mp; 143765679Shibler struct netexport *nep; 143865679Shibler struct mbuf *nam; 143965679Shibler { 144065679Shibler register struct netcred *np; 144165679Shibler register struct radix_node_head *rnh; 144265679Shibler struct sockaddr *saddr; 144365679Shibler 144465679Shibler np = NULL; 144565679Shibler if (mp->mnt_flag & MNT_EXPORTED) { 144665679Shibler /* 144765679Shibler * Lookup in the export list first. 144865679Shibler */ 144965679Shibler if (nam != NULL) { 145065679Shibler saddr = mtod(nam, struct sockaddr *); 145165679Shibler rnh = nep->ne_rtable[saddr->sa_family]; 145265679Shibler if (rnh != NULL) { 145365679Shibler np = (struct netcred *) 145465679Shibler (*rnh->rnh_matchaddr)((caddr_t)saddr, 145565679Shibler rnh); 145665679Shibler if (np && np->netc_rnodes->rn_flags & RNF_ROOT) 145765679Shibler np = NULL; 145865679Shibler } 145965679Shibler } 146065679Shibler /* 146165679Shibler * If no address match, use the default if it exists. 146265679Shibler */ 146365679Shibler if (np == NULL && mp->mnt_flag & MNT_DEFEXPORTED) 146465679Shibler np = &nep->ne_defexported; 146565679Shibler } 146665679Shibler return (np); 146765679Shibler } 1468