137488Smckusick /* 237488Smckusick * Copyright (c) 1989 The Regents of the University of California. 337488Smckusick * All rights reserved. 437488Smckusick * 537488Smckusick * Redistribution and use in source and binary forms are permitted 637488Smckusick * provided that the above copyright notice and this paragraph are 737488Smckusick * duplicated in all such forms and that any documentation, 837488Smckusick * advertising materials, and other materials related to such 937488Smckusick * distribution and use acknowledge that the software was developed 1037488Smckusick * by the University of California, Berkeley. The name of the 1137488Smckusick * University may not be used to endorse or promote products derived 1237488Smckusick * from this software without specific prior written permission. 1337488Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437488Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537488Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637488Smckusick * 17*39433Smckusick * @(#)vfs_subr.c 7.9 (Berkeley) 10/29/89 1837488Smckusick */ 1937488Smckusick 2037488Smckusick /* 2137488Smckusick * External virtual filesystem routines 2237488Smckusick */ 2337488Smckusick 2437488Smckusick #include "param.h" 2537488Smckusick #include "mount.h" 2637488Smckusick #include "time.h" 2737488Smckusick #include "vnode.h" 2838265Smckusick #include "namei.h" 2938265Smckusick #include "ucred.h" 3037488Smckusick #include "errno.h" 31*39433Smckusick #include "malloc.h" 3237488Smckusick 3337488Smckusick /* 3437488Smckusick * Remove a mount point from the list of mounted filesystems. 3537488Smckusick * Unmount of the root is illegal. 3637488Smckusick */ 3737488Smckusick void 3837488Smckusick vfs_remove(mp) 3937488Smckusick register struct mount *mp; 4037488Smckusick { 4137488Smckusick 4237488Smckusick if (mp == rootfs) 4337488Smckusick panic("vfs_remove: unmounting root"); 4437488Smckusick mp->m_prev->m_next = mp->m_next; 4537488Smckusick mp->m_next->m_prev = mp->m_prev; 4637488Smckusick mp->m_vnodecovered->v_mountedhere = (struct mount *)0; 4737488Smckusick vfs_unlock(mp); 4837488Smckusick } 4937488Smckusick 5037488Smckusick /* 5137488Smckusick * Lock a filesystem. 5237488Smckusick * Used to prevent access to it while mounting and unmounting. 5337488Smckusick */ 5437488Smckusick vfs_lock(mp) 5537488Smckusick register struct mount *mp; 5637488Smckusick { 5737488Smckusick 5839045Smckusick while(mp->m_flag & M_MLOCK) { 5939045Smckusick mp->m_flag |= M_MWAIT; 6039045Smckusick sleep((caddr_t)mp, PVFS); 6139045Smckusick } 6237488Smckusick mp->m_flag |= M_MLOCK; 6337488Smckusick return (0); 6437488Smckusick } 6537488Smckusick 6637488Smckusick /* 6737488Smckusick * Unlock a locked filesystem. 6837488Smckusick * Panic if filesystem is not locked. 6937488Smckusick */ 7037488Smckusick void 7137488Smckusick vfs_unlock(mp) 7237488Smckusick register struct mount *mp; 7337488Smckusick { 7437488Smckusick 7537488Smckusick if ((mp->m_flag & M_MLOCK) == 0) 7637488Smckusick panic("vfs_unlock: locked fs"); 7737488Smckusick mp->m_flag &= ~M_MLOCK; 7837488Smckusick if (mp->m_flag & M_MWAIT) { 7937488Smckusick mp->m_flag &= ~M_MWAIT; 8037488Smckusick wakeup((caddr_t)mp); 8137488Smckusick } 8237488Smckusick } 8337488Smckusick 8437488Smckusick /* 8537488Smckusick * Lookup a mount point by filesystem identifier. 8637488Smckusick */ 8737488Smckusick struct mount * 8837488Smckusick getvfs(fsid) 8937488Smckusick fsid_t *fsid; 9037488Smckusick { 9137488Smckusick register struct mount *mp; 9237488Smckusick 9338288Smckusick mp = rootfs; 9438288Smckusick do { 9537488Smckusick if (mp->m_fsid.val[0] == fsid->val[0] && 9637488Smckusick mp->m_fsid.val[1] == fsid->val[1]) { 9738288Smckusick return (mp); 9837488Smckusick } 9938288Smckusick mp = mp->m_next; 10038288Smckusick } while (mp != rootfs); 10138288Smckusick return ((struct mount *)0); 10237488Smckusick } 10337488Smckusick 10437488Smckusick /* 10537488Smckusick * Set vnode attributes to VNOVAL 10637488Smckusick */ 10737488Smckusick void vattr_null(vap) 10837488Smckusick register struct vattr *vap; 10937488Smckusick { 11037488Smckusick 11137488Smckusick vap->va_type = VNON; 11237488Smckusick vap->va_mode = vap->va_nlink = vap->va_uid = vap->va_gid = 11337488Smckusick vap->va_fsid = vap->va_fileid = vap->va_size = 11437488Smckusick vap->va_size1 = vap->va_blocksize = vap->va_rdev = 11537488Smckusick vap->va_bytes = vap->va_bytes1 = 11637488Smckusick vap->va_atime.tv_sec = vap->va_atime.tv_usec = 11737488Smckusick vap->va_mtime.tv_sec = vap->va_mtime.tv_usec = 11838258Smckusick vap->va_ctime.tv_sec = vap->va_ctime.tv_usec = 11938258Smckusick vap->va_flags = vap->va_gen = VNOVAL; 12037488Smckusick } 12138265Smckusick 12238265Smckusick /* 12338265Smckusick * Initialize a nameidata structure 12438265Smckusick */ 12538265Smckusick ndinit(ndp) 12638265Smckusick register struct nameidata *ndp; 12738265Smckusick { 12838265Smckusick 12938265Smckusick bzero((caddr_t)ndp, sizeof(struct nameidata)); 13038265Smckusick ndp->ni_iov = &ndp->ni_nd.nd_iovec; 13138265Smckusick ndp->ni_iovcnt = 1; 13238265Smckusick ndp->ni_base = (caddr_t)&ndp->ni_dent; 13338265Smckusick ndp->ni_rw = UIO_WRITE; 13438265Smckusick ndp->ni_segflg = UIO_SYSSPACE; 13538265Smckusick } 13638265Smckusick 13738265Smckusick /* 13838265Smckusick * Duplicate a nameidata structure 13938265Smckusick */ 14038265Smckusick nddup(ndp, newndp) 14138265Smckusick register struct nameidata *ndp, *newndp; 14238265Smckusick { 14338265Smckusick 14438265Smckusick ndinit(newndp); 14538265Smckusick newndp->ni_cdir = ndp->ni_cdir; 14638348Smckusick VREF(newndp->ni_cdir); 14738265Smckusick newndp->ni_rdir = ndp->ni_rdir; 14838265Smckusick if (newndp->ni_rdir) 14938348Smckusick VREF(newndp->ni_rdir); 15038265Smckusick newndp->ni_cred = ndp->ni_cred; 15138265Smckusick crhold(newndp->ni_cred); 15238265Smckusick } 15338265Smckusick 15438265Smckusick /* 15538265Smckusick * Release a nameidata structure 15638265Smckusick */ 15738265Smckusick ndrele(ndp) 15838265Smckusick register struct nameidata *ndp; 15938265Smckusick { 16038265Smckusick 16138265Smckusick vrele(ndp->ni_cdir); 16238265Smckusick if (ndp->ni_rdir) 16338265Smckusick vrele(ndp->ni_rdir); 16438265Smckusick crfree(ndp->ni_cred); 16538265Smckusick } 16639397Smckusick 16739397Smckusick /* 16839397Smckusick * Routines having to do with the management of the vnode table. 16939397Smckusick */ 17039397Smckusick struct vnode *vfreeh, **vfreet; 171*39433Smckusick extern struct vnodeops dead_vnodeops, blk_vnodeops; 172*39433Smckusick struct speclist *speclisth; 173*39433Smckusick struct speclist { 174*39433Smckusick struct speclist *sl_next; 175*39433Smckusick struct vnode *sl_vp; 176*39433Smckusick }; 17739397Smckusick 17839397Smckusick /* 179*39433Smckusick * Initialize the vnode structures and initialize each file system type. 18039397Smckusick */ 181*39433Smckusick vfsinit() 18239397Smckusick { 18339397Smckusick register struct vnode *vp = vnode; 184*39433Smckusick struct vfsops **vfsp; 18539397Smckusick 186*39433Smckusick /* 187*39433Smckusick * Build vnode free list. 188*39433Smckusick */ 18939397Smckusick vfreeh = vp; 19039397Smckusick vfreet = &vp->v_freef; 19139397Smckusick vp->v_freeb = &vfreeh; 19239397Smckusick vp->v_op = &dead_vnodeops; 19339397Smckusick for (vp++; vp < vnodeNVNODE; vp++) { 19439397Smckusick *vfreet = vp; 19539397Smckusick vp->v_freeb = vfreet; 19639397Smckusick vfreet = &vp->v_freef; 19739397Smckusick vp->v_op = &dead_vnodeops; 19839397Smckusick } 19939397Smckusick vp--; 20039397Smckusick vp->v_freef = NULL; 201*39433Smckusick /* 202*39433Smckusick * Initialize the vnode name cache 203*39433Smckusick */ 204*39433Smckusick nchinit(); 205*39433Smckusick /* 206*39433Smckusick * Initialize each file system type. 207*39433Smckusick */ 208*39433Smckusick for (vfsp = &vfssw[0]; vfsp <= &vfssw[MOUNT_MAXTYPE]; vfsp++) { 209*39433Smckusick if (*vfsp == NULL) 210*39433Smckusick continue; 211*39433Smckusick (*(*vfsp)->vfs_init)(); 212*39433Smckusick } 21339397Smckusick } 21439397Smckusick 21539397Smckusick /* 21639397Smckusick * Return the next vnode from the free list. 21739397Smckusick */ 21839397Smckusick getnewvnode(tag, mp, vops, vpp) 21939397Smckusick enum vtagtype tag; 22039397Smckusick struct mount *mp; 22139397Smckusick struct vnodeops *vops; 22239397Smckusick struct vnode **vpp; 22339397Smckusick { 22439397Smckusick register struct vnode *vp, *vq; 22539397Smckusick 22639397Smckusick if ((vp = vfreeh) == NULL) { 22739397Smckusick tablefull("vnode"); 22839397Smckusick *vpp = 0; 22939397Smckusick return (ENFILE); 23039397Smckusick } 231*39433Smckusick if (vp->v_count) 23239397Smckusick panic("free vnode isn't"); 23339397Smckusick if (vq = vp->v_freef) 23439397Smckusick vq->v_freeb = &vfreeh; 23539397Smckusick vfreeh = vq; 23639397Smckusick vp->v_freef = NULL; 23739397Smckusick vp->v_freeb = NULL; 238*39433Smckusick if (vp->v_type != VNON) 239*39433Smckusick vgone(vp); 24039397Smckusick vp->v_flag = 0; 24139397Smckusick vp->v_shlockc = 0; 24239397Smckusick vp->v_exlockc = 0; 24339397Smckusick vp->v_socket = 0; 24439397Smckusick cache_purge(vp); 24539397Smckusick vp->v_tag = tag; 246*39433Smckusick vp->v_op = vops; 24739397Smckusick vp->v_mount = mp; 24839397Smckusick insmntque(vp, mp); 24939397Smckusick VREF(vp); 25039397Smckusick *vpp = vp; 25139397Smckusick return (0); 25239397Smckusick } 25339397Smckusick 25439397Smckusick /* 25539397Smckusick * Move a vnode from one mount queue to another. 25639397Smckusick */ 25739397Smckusick insmntque(vp, mp) 25839397Smckusick register struct vnode *vp; 25939397Smckusick register struct mount *mp; 26039397Smckusick { 26139397Smckusick struct vnode *vq; 26239397Smckusick 26339397Smckusick /* 26439397Smckusick * Delete from old mount point vnode list, if on one. 26539397Smckusick */ 26639397Smckusick if (vp->v_mountb) { 26739397Smckusick if (vq = vp->v_mountf) 26839397Smckusick vq->v_mountb = vp->v_mountb; 26939397Smckusick *vp->v_mountb = vq; 27039397Smckusick } 27139397Smckusick /* 27239397Smckusick * Insert into list of vnodes for the new mount point, if available. 27339397Smckusick */ 27439397Smckusick if (mp == NULL) { 27539397Smckusick vp->v_mountf = NULL; 27639397Smckusick vp->v_mountb = NULL; 27739397Smckusick return; 27839397Smckusick } 27939397Smckusick if (mp->m_mounth) { 28039397Smckusick vp->v_mountf = mp->m_mounth; 28139397Smckusick vp->v_mountb = &mp->m_mounth; 28239397Smckusick mp->m_mounth->v_mountb = &vp->v_mountf; 28339397Smckusick mp->m_mounth = vp; 28439397Smckusick } else { 28539397Smckusick mp->m_mounth = vp; 28639397Smckusick vp->v_mountb = &mp->m_mounth; 28739397Smckusick vp->v_mountf = NULL; 28839397Smckusick } 28939397Smckusick } 29039397Smckusick 29139397Smckusick /* 292*39433Smckusick * Create a vnode for a block device. 293*39433Smckusick * Used for root filesystem, argdev, and swap areas. 294*39433Smckusick * Also used for memory file system special devices. 29539397Smckusick */ 296*39433Smckusick bdevvp(dev, vpp) 297*39433Smckusick dev_t dev; 298*39433Smckusick struct vnode **vpp; 299*39433Smckusick { 300*39433Smckusick register struct inode *ip; 301*39433Smckusick register struct vnode *vp; 302*39433Smckusick struct vnode *nvp; 303*39433Smckusick int error; 304*39433Smckusick 305*39433Smckusick error = getnewvnode(VT_NON, (struct mount *)0, &blk_vnodeops, &nvp); 306*39433Smckusick if (error) { 307*39433Smckusick *vpp = 0; 308*39433Smckusick return (error); 309*39433Smckusick } 310*39433Smckusick vp = nvp; 311*39433Smckusick vp->v_type = VBLK; 312*39433Smckusick vp->v_rdev = dev; 313*39433Smckusick if (nvp = checkalias(vp, (struct mount *)0)) { 314*39433Smckusick vput(vp); 315*39433Smckusick vp = nvp; 316*39433Smckusick } 317*39433Smckusick *vpp = vp; 318*39433Smckusick return (0); 319*39433Smckusick } 320*39433Smckusick 321*39433Smckusick /* 322*39433Smckusick * Check to see if the new vnode represents a special device 323*39433Smckusick * for which we already have a vnode (either because of 324*39433Smckusick * bdevvp() or because of a different vnode representing 325*39433Smckusick * the same block device). If such an alias exists, deallocate 326*39433Smckusick * the existing contents and return the aliased inode. The 327*39433Smckusick * caller is responsible for filling it with its new contents. 328*39433Smckusick */ 329*39433Smckusick struct vnode * 330*39433Smckusick checkalias(nvp, mp) 331*39433Smckusick register struct vnode *nvp; 332*39433Smckusick struct mount *mp; 333*39433Smckusick { 334*39433Smckusick register struct vnode *vp; 335*39433Smckusick register struct speclist *slp; 336*39433Smckusick 337*39433Smckusick if (nvp->v_type != VBLK && nvp->v_type != VCHR) 338*39433Smckusick return ((struct vnode *)0); 339*39433Smckusick loop: 340*39433Smckusick for (slp = speclisth; slp; slp = slp->sl_next) { 341*39433Smckusick vp = slp->sl_vp; 342*39433Smckusick if (nvp->v_rdev != vp->v_rdev || 343*39433Smckusick nvp->v_type != vp->v_type) 344*39433Smckusick continue; 345*39433Smckusick if (vget(vp)) 346*39433Smckusick goto loop; 347*39433Smckusick break; 348*39433Smckusick } 349*39433Smckusick if (slp == NULL) { 350*39433Smckusick MALLOC(slp, struct speclist *, sizeof(*slp), M_VNODE, M_WAITOK); 351*39433Smckusick slp->sl_vp = nvp; 352*39433Smckusick slp->sl_next = speclisth; 353*39433Smckusick speclisth = slp; 354*39433Smckusick return ((struct vnode *)0); 355*39433Smckusick } 356*39433Smckusick vclean(vp); 357*39433Smckusick vp->v_op = nvp->v_op; 358*39433Smckusick vp->v_tag = nvp->v_tag; 359*39433Smckusick nvp->v_type = VNON; 360*39433Smckusick insmntque(vp, mp); 361*39433Smckusick return (vp); 362*39433Smckusick } 363*39433Smckusick 364*39433Smckusick /* 365*39433Smckusick * Grab a particular vnode from the free list, increment its 366*39433Smckusick * reference count and lock it. The vnode lock bit is set the 367*39433Smckusick * vnode is being eliminated in vgone. The process is awakened 368*39433Smckusick * when the transition is completed, and an error returned to 369*39433Smckusick * indicate that the vnode is no longer usable (possibly having 370*39433Smckusick * been changed to a new file system type). 371*39433Smckusick */ 37239397Smckusick vget(vp) 37339397Smckusick register struct vnode *vp; 37439397Smckusick { 37539397Smckusick register struct vnode *vq; 37639397Smckusick 377*39433Smckusick if (vp->v_flag & VXLOCK) { 378*39433Smckusick vp->v_flag |= VXWANT; 379*39433Smckusick sleep((caddr_t)vp, PINOD); 380*39433Smckusick return (1); 381*39433Smckusick } 382*39433Smckusick if (vp->v_count == 0) { 383*39433Smckusick if (vq = vp->v_freef) 384*39433Smckusick vq->v_freeb = vp->v_freeb; 385*39433Smckusick else 386*39433Smckusick vfreet = vp->v_freeb; 387*39433Smckusick *vp->v_freeb = vq; 388*39433Smckusick vp->v_freef = NULL; 389*39433Smckusick vp->v_freeb = NULL; 390*39433Smckusick } 39139397Smckusick VREF(vp); 392*39433Smckusick VOP_LOCK(vp); 393*39433Smckusick return (0); 39439397Smckusick } 39539397Smckusick 39639397Smckusick /* 39739397Smckusick * Vnode reference, just increment the count 39839397Smckusick */ 39939397Smckusick void vref(vp) 40039397Smckusick struct vnode *vp; 40139397Smckusick { 40239397Smckusick 40339397Smckusick vp->v_count++; 40439397Smckusick } 40539397Smckusick 40639397Smckusick /* 40739397Smckusick * vput(), just unlock and vrele() 40839397Smckusick */ 40939397Smckusick void vput(vp) 41039397Smckusick register struct vnode *vp; 41139397Smckusick { 41239397Smckusick VOP_UNLOCK(vp); 41339397Smckusick vrele(vp); 41439397Smckusick } 41539397Smckusick 41639397Smckusick /* 41739397Smckusick * Vnode release. 41839397Smckusick * If count drops to zero, call inactive routine and return to freelist. 41939397Smckusick */ 42039397Smckusick void vrele(vp) 42139397Smckusick register struct vnode *vp; 42239397Smckusick { 42339397Smckusick 42439397Smckusick if (vp == NULL) 425*39433Smckusick panic("vrele: null vp"); 42639397Smckusick vp->v_count--; 42739397Smckusick if (vp->v_count < 0) 42839397Smckusick printf("vnode bad ref count %d, type %d, tag %d\n", 42939397Smckusick vp->v_count, vp->v_type, vp->v_tag); 43039397Smckusick if (vp->v_count > 0) 43139397Smckusick return; 43239397Smckusick if (vfreeh == (struct vnode *)0) { 43339397Smckusick /* 43439397Smckusick * insert into empty list 43539397Smckusick */ 43639397Smckusick vfreeh = vp; 43739397Smckusick vp->v_freeb = &vfreeh; 43839397Smckusick } else { 43939397Smckusick /* 44039397Smckusick * insert at tail of list 44139397Smckusick */ 44239397Smckusick *vfreet = vp; 44339397Smckusick vp->v_freeb = vfreet; 44439397Smckusick } 445*39433Smckusick vp->v_freef = NULL; 446*39433Smckusick vfreet = &vp->v_freef; 447*39433Smckusick VOP_INACTIVE(vp); 44839397Smckusick } 449*39433Smckusick 450*39433Smckusick /* 451*39433Smckusick * Disassociate the underlying file system from a vnode. 452*39433Smckusick * If this operation is done on an active vnode (i.e. v_count > 0) 453*39433Smckusick * then the vnode must be delivered locked. 454*39433Smckusick */ 455*39433Smckusick void vclean(vp) 456*39433Smckusick register struct vnode *vp; 457*39433Smckusick { 458*39433Smckusick struct vnodeops *origops; 459*39433Smckusick 460*39433Smckusick while (vp->v_flag & VXLOCK) { 461*39433Smckusick vp->v_flag |= VXWANT; 462*39433Smckusick sleep((caddr_t)vp, PINOD); 463*39433Smckusick } 464*39433Smckusick vp->v_flag |= VXLOCK; 465*39433Smckusick /* 466*39433Smckusick * Prevent any further operations on the vnode from 467*39433Smckusick * being passed through to the old file system. 468*39433Smckusick */ 469*39433Smckusick origops = vp->v_op; 470*39433Smckusick vp->v_op = &dead_vnodeops; 471*39433Smckusick vp->v_tag = VT_NON; 472*39433Smckusick /* 473*39433Smckusick * If purging an active vnode, it must be unlocked and 474*39433Smckusick * deactivated before being reclaimed. 475*39433Smckusick */ 476*39433Smckusick if (vp->v_count > 0) { 477*39433Smckusick (*(origops->vn_unlock))(vp); 478*39433Smckusick (*(origops->vn_inactive))(vp); 479*39433Smckusick } 480*39433Smckusick /* 481*39433Smckusick * Reclaim the vnode. 482*39433Smckusick */ 483*39433Smckusick if ((*(origops->vn_reclaim))(vp)) 484*39433Smckusick panic("vclean: cannot reclaim"); 485*39433Smckusick /* 486*39433Smckusick * Done with purge, notify sleepers in vget of the grim news. 487*39433Smckusick */ 488*39433Smckusick vp->v_flag &= ~VXLOCK; 489*39433Smckusick if (vp->v_flag & VXWANT) { 490*39433Smckusick vp->v_flag &= ~VXWANT; 491*39433Smckusick wakeup((caddr_t)vp); 492*39433Smckusick } 493*39433Smckusick } 494*39433Smckusick 495*39433Smckusick /* 496*39433Smckusick * Eliminate all activity associated with a vnode 497*39433Smckusick * in preparation for reuse. 498*39433Smckusick */ 499*39433Smckusick void vgone(vp) 500*39433Smckusick register struct vnode *vp; 501*39433Smckusick { 502*39433Smckusick register struct speclist *slp; 503*39433Smckusick struct speclist *pslp; 504*39433Smckusick register struct vnode *vq; 505*39433Smckusick 506*39433Smckusick if (vp->v_count > 0) 507*39433Smckusick panic("vgone: cannot reclaim"); 508*39433Smckusick /* 509*39433Smckusick * Clean out the filesystem specific data. 510*39433Smckusick */ 511*39433Smckusick vclean(vp); 512*39433Smckusick /* 513*39433Smckusick * Delete from old mount point vnode list, if on one. 514*39433Smckusick */ 515*39433Smckusick if (vp->v_mountb) { 516*39433Smckusick if (vq = vp->v_mountf) 517*39433Smckusick vq->v_mountb = vp->v_mountb; 518*39433Smckusick *vp->v_mountb = vq; 519*39433Smckusick vp->v_mountf = NULL; 520*39433Smckusick vp->v_mountb = NULL; 521*39433Smckusick } 522*39433Smckusick /* 523*39433Smckusick * If special device, remove it from special device alias list. 524*39433Smckusick */ 525*39433Smckusick if (vp->v_type == VBLK || vp->v_type == VCHR) { 526*39433Smckusick if (speclisth->sl_vp == vp) { 527*39433Smckusick slp = speclisth; 528*39433Smckusick speclisth = slp->sl_next; 529*39433Smckusick } else { 530*39433Smckusick for (slp = speclisth; slp; 531*39433Smckusick pslp = slp, slp = slp->sl_next) { 532*39433Smckusick if (slp->sl_vp != vp) 533*39433Smckusick continue; 534*39433Smckusick pslp->sl_next = slp->sl_next; 535*39433Smckusick break; 536*39433Smckusick } 537*39433Smckusick if (slp == NULL) 538*39433Smckusick panic("missing bdev"); 539*39433Smckusick } 540*39433Smckusick FREE(slp, M_VNODE); 541*39433Smckusick } 542*39433Smckusick /* 543*39433Smckusick * If it is on the freelist, move it to the head of the list. 544*39433Smckusick */ 545*39433Smckusick if (vp->v_freeb) { 546*39433Smckusick if (vq = vp->v_freef) 547*39433Smckusick vq->v_freeb = vp->v_freeb; 548*39433Smckusick else 549*39433Smckusick vfreet = vp->v_freeb; 550*39433Smckusick *vp->v_freeb = vq; 551*39433Smckusick vp->v_freef = vfreeh; 552*39433Smckusick vp->v_freeb = &vfreeh; 553*39433Smckusick vfreeh->v_freeb = &vp->v_freef; 554*39433Smckusick vfreeh = vp; 555*39433Smckusick } 556*39433Smckusick vp->v_type = VNON; 557*39433Smckusick } 558