123405Smckusick /* 251502Sbostic * Copyright (c) 1986, 1989, 1991 Regents of the University of California. 337737Smckusick * All rights reserved. 423405Smckusick * 544539Sbostic * %sccs.include.redist.c% 637737Smckusick * 7*54030Smckusick * @(#)lfs_vnops.c 7.84 (Berkeley) 06/17/92 823405Smckusick */ 937Sbill 1051482Sbostic #include <sys/param.h> 1151482Sbostic #include <sys/systm.h> 1251482Sbostic #include <sys/namei.h> 1351482Sbostic #include <sys/resourcevar.h> 1451482Sbostic #include <sys/kernel.h> 1551482Sbostic #include <sys/file.h> 1651482Sbostic #include <sys/stat.h> 1751482Sbostic #include <sys/buf.h> 1851482Sbostic #include <sys/proc.h> 1951482Sbostic #include <sys/conf.h> 2051482Sbostic #include <sys/mount.h> 2151482Sbostic #include <sys/vnode.h> 2251482Sbostic #include <sys/specdev.h> 2351482Sbostic #include <sys/fifo.h> 2451482Sbostic #include <sys/malloc.h> 2537Sbill 2653321Smckusick #include <vm/vm.h> 2753321Smckusick 2851502Sbostic #include <ufs/ufs/quota.h> 2951502Sbostic #include <ufs/ufs/inode.h> 3051502Sbostic #include <ufs/ufs/dir.h> 3151502Sbostic #include <ufs/ufs/ufs_extern.h> 3247571Skarels 3351502Sbostic #include <ufs/lfs/lfs.h> 3451502Sbostic #include <ufs/lfs/lfs_extern.h> 3551134Sbostic 3651482Sbostic /* Global vfs data structures for lfs. */ 3753533Sheideman int (**lfs_vnodeop_p)(); 3853533Sheideman struct vnodeopv_entry_desc lfs_vnodeop_entries[] = { 3953533Sheideman { &vop_default_desc, vn_default_error }, 4053533Sheideman { &vop_lookup_desc, ufs_lookup }, /* lookup */ 4153533Sheideman { &vop_create_desc, ufs_create }, /* create */ 42*54030Smckusick { &vop_mknod_desc, ufs_mknod }, /* mknod */ 43*54030Smckusick { &vop_open_desc, ufs_open }, /* open */ 44*54030Smckusick { &vop_close_desc, ufs_close }, /* close */ 4553533Sheideman { &vop_access_desc, ufs_access }, /* access */ 4653533Sheideman { &vop_getattr_desc, ufs_getattr }, /* getattr */ 4753533Sheideman { &vop_setattr_desc, ufs_setattr }, /* setattr */ 48*54030Smckusick { &vop_read_desc, lfs_read }, /* read */ 49*54030Smckusick { &vop_write_desc, lfs_write }, /* write */ 50*54030Smckusick { &vop_ioctl_desc, ufs_ioctl }, /* ioctl */ 5153533Sheideman { &vop_select_desc, ufs_select }, /* select */ 52*54030Smckusick { &vop_mmap_desc, ufs_mmap }, /* mmap */ 53*54030Smckusick { &vop_fsync_desc, lfs_fsync }, /* fsync */ 54*54030Smckusick { &vop_seek_desc, ufs_seek }, /* seek */ 5553533Sheideman { &vop_remove_desc, ufs_remove }, /* remove */ 56*54030Smckusick { &vop_link_desc, ufs_link }, /* link */ 5753533Sheideman { &vop_rename_desc, ufs_rename }, /* rename */ 58*54030Smckusick { &vop_mkdir_desc, ufs_mkdir }, /* mkdir */ 59*54030Smckusick { &vop_rmdir_desc, ufs_rmdir }, /* rmdir */ 6053533Sheideman { &vop_symlink_desc, ufs_symlink }, /* symlink */ 6153533Sheideman { &vop_readdir_desc, ufs_readdir }, /* readdir */ 6253533Sheideman { &vop_readlink_desc, ufs_readlink }, /* readlink */ 6353533Sheideman { &vop_abortop_desc, ufs_abortop }, /* abortop */ 6453533Sheideman { &vop_inactive_desc, lfs_inactive }, /* inactive */ 6553533Sheideman { &vop_reclaim_desc, ufs_reclaim }, /* reclaim */ 66*54030Smckusick { &vop_lock_desc, ufs_lock }, /* lock */ 6753533Sheideman { &vop_unlock_desc, ufs_unlock }, /* unlock */ 68*54030Smckusick { &vop_bmap_desc, lfs_bmap }, /* bmap */ 6953533Sheideman { &vop_strategy_desc, ufs_strategy }, /* strategy */ 70*54030Smckusick { &vop_print_desc, ufs_print }, /* print */ 7153533Sheideman { &vop_islocked_desc, ufs_islocked }, /* islocked */ 7253533Sheideman { &vop_advlock_desc, ufs_advlock }, /* advlock */ 7353533Sheideman { &vop_blkatoff_desc, lfs_blkatoff }, /* blkatoff */ 74*54030Smckusick { &vop_vget_desc, lfs_vget }, /* vget */ 7553533Sheideman { &vop_valloc_desc, lfs_valloc }, /* valloc */ 76*54030Smckusick { &vop_vfree_desc, lfs_vfree }, /* vfree */ 7753533Sheideman { &vop_truncate_desc, lfs_truncate }, /* truncate */ 7853533Sheideman { &vop_update_desc, lfs_update }, /* update */ 7953533Sheideman { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */ 8053533Sheideman { (struct vnodeop_desc*)NULL, (int(*)())NULL } 8151482Sbostic }; 8253533Sheideman struct vnodeopv_desc lfs_vnodeop_opv_desc = 8353533Sheideman { &lfs_vnodeop_p, lfs_vnodeop_entries }; 846254Sroot 8553533Sheideman int (**lfs_specop_p)(); 8653533Sheideman struct vnodeopv_entry_desc lfs_specop_entries[] = { 8753533Sheideman { &vop_default_desc, vn_default_error }, 8853533Sheideman { &vop_lookup_desc, spec_lookup }, /* lookup */ 8953533Sheideman { &vop_create_desc, spec_create }, /* create */ 9053533Sheideman { &vop_mknod_desc, spec_mknod }, /* mknod */ 91*54030Smckusick { &vop_open_desc, spec_open }, /* open */ 9253533Sheideman { &vop_close_desc, ufsspec_close }, /* close */ 9353533Sheideman { &vop_access_desc, ufs_access }, /* access */ 9453533Sheideman { &vop_getattr_desc, ufs_getattr }, /* getattr */ 9553533Sheideman { &vop_setattr_desc, ufs_setattr }, /* setattr */ 9653533Sheideman { &vop_read_desc, ufsspec_read }, /* read */ 9753533Sheideman { &vop_write_desc, ufsspec_write }, /* write */ 9853533Sheideman { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ 9953533Sheideman { &vop_select_desc, spec_select }, /* select */ 100*54030Smckusick { &vop_mmap_desc, spec_mmap }, /* mmap */ 10153533Sheideman { &vop_fsync_desc, spec_fsync }, /* fsync */ 102*54030Smckusick { &vop_seek_desc, spec_seek }, /* seek */ 10353533Sheideman { &vop_remove_desc, spec_remove }, /* remove */ 104*54030Smckusick { &vop_link_desc, spec_link }, /* link */ 10553533Sheideman { &vop_rename_desc, spec_rename }, /* rename */ 10653533Sheideman { &vop_mkdir_desc, spec_mkdir }, /* mkdir */ 10753533Sheideman { &vop_rmdir_desc, spec_rmdir }, /* rmdir */ 10853533Sheideman { &vop_symlink_desc, spec_symlink }, /* symlink */ 10953533Sheideman { &vop_readdir_desc, spec_readdir }, /* readdir */ 11053533Sheideman { &vop_readlink_desc, spec_readlink }, /* readlink */ 11153533Sheideman { &vop_abortop_desc, spec_abortop }, /* abortop */ 11253533Sheideman { &vop_inactive_desc, lfs_inactive }, /* inactive */ 11353533Sheideman { &vop_reclaim_desc, ufs_reclaim }, /* reclaim */ 114*54030Smckusick { &vop_lock_desc, ufs_lock }, /* lock */ 11553533Sheideman { &vop_unlock_desc, ufs_unlock }, /* unlock */ 116*54030Smckusick { &vop_bmap_desc, spec_bmap }, /* bmap */ 11753533Sheideman { &vop_strategy_desc, spec_strategy }, /* strategy */ 118*54030Smckusick { &vop_print_desc, ufs_print }, /* print */ 11953533Sheideman { &vop_islocked_desc, ufs_islocked }, /* islocked */ 12053533Sheideman { &vop_advlock_desc, spec_advlock }, /* advlock */ 12153533Sheideman { &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */ 122*54030Smckusick { &vop_vget_desc, spec_vget }, /* vget */ 12353533Sheideman { &vop_valloc_desc, spec_valloc }, /* valloc */ 124*54030Smckusick { &vop_vfree_desc, lfs_vfree }, /* vfree */ 12553533Sheideman { &vop_truncate_desc, spec_truncate }, /* truncate */ 12653533Sheideman { &vop_update_desc, lfs_update }, /* update */ 12753533Sheideman { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */ 12853533Sheideman { (struct vnodeop_desc*)NULL, (int(*)())NULL } 12951558Smckusick }; 13053533Sheideman struct vnodeopv_desc lfs_specop_opv_desc = 13153533Sheideman { &lfs_specop_p, lfs_specop_entries }; 13251558Smckusick 13351558Smckusick #ifdef FIFO 13453533Sheideman int (**lfs_fifoop_p)(); 13553533Sheideman struct vnodeopv_entry_desc lfs_fifoop_entries[] = { 13653533Sheideman { &vop_default_desc, vn_default_error }, 13753533Sheideman { &vop_lookup_desc, fifo_lookup }, /* lookup */ 13853533Sheideman { &vop_create_desc, fifo_create }, /* create */ 13953533Sheideman { &vop_mknod_desc, fifo_mknod }, /* mknod */ 140*54030Smckusick { &vop_open_desc, fifo_open }, /* open */ 14153533Sheideman { &vop_close_desc, ufsfifo_close }, /* close */ 14253533Sheideman { &vop_access_desc, ufs_access }, /* access */ 14353533Sheideman { &vop_getattr_desc, ufs_getattr }, /* getattr */ 14453533Sheideman { &vop_setattr_desc, ufs_setattr }, /* setattr */ 14553533Sheideman { &vop_read_desc, ufsfifo_read }, /* read */ 14653533Sheideman { &vop_write_desc, ufsfifo_write }, /* write */ 14753533Sheideman { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ 14853533Sheideman { &vop_select_desc, fifo_select }, /* select */ 149*54030Smckusick { &vop_mmap_desc, fifo_mmap }, /* mmap */ 15053533Sheideman { &vop_fsync_desc, fifo_fsync }, /* fsync */ 151*54030Smckusick { &vop_seek_desc, fifo_seek }, /* seek */ 15253533Sheideman { &vop_remove_desc, fifo_remove }, /* remove */ 153*54030Smckusick { &vop_link_desc, fifo_link }, /* link */ 15453533Sheideman { &vop_rename_desc, fifo_rename }, /* rename */ 15553533Sheideman { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ 15653533Sheideman { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ 15753533Sheideman { &vop_symlink_desc, fifo_symlink }, /* symlink */ 15853533Sheideman { &vop_readdir_desc, fifo_readdir }, /* readdir */ 15953533Sheideman { &vop_readlink_desc, fifo_readlink }, /* readlink */ 16053533Sheideman { &vop_abortop_desc, fifo_abortop }, /* abortop */ 16153533Sheideman { &vop_inactive_desc, lfs_inactive }, /* inactive */ 16253533Sheideman { &vop_reclaim_desc, ufs_reclaim }, /* reclaim */ 163*54030Smckusick { &vop_lock_desc, ufs_lock }, /* lock */ 16453533Sheideman { &vop_unlock_desc, ufs_unlock }, /* unlock */ 165*54030Smckusick { &vop_bmap_desc, fifo_bmap }, /* bmap */ 16653533Sheideman { &vop_strategy_desc, fifo_strategy }, /* strategy */ 167*54030Smckusick { &vop_print_desc, ufs_print }, /* print */ 16853533Sheideman { &vop_islocked_desc, ufs_islocked }, /* islocked */ 16953533Sheideman { &vop_advlock_desc, fifo_advlock }, /* advlock */ 17053533Sheideman { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */ 171*54030Smckusick { &vop_vget_desc, fifo_vget }, /* vget */ 17253533Sheideman { &vop_valloc_desc, fifo_valloc }, /* valloc */ 173*54030Smckusick { &vop_vfree_desc, lfs_vfree }, /* vfree */ 17453533Sheideman { &vop_truncate_desc, fifo_truncate }, /* truncate */ 17553533Sheideman { &vop_update_desc, lfs_update }, /* update */ 17653533Sheideman { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */ 17753533Sheideman { (struct vnodeop_desc*)NULL, (int(*)())NULL } 17851558Smckusick }; 17953533Sheideman struct vnodeopv_desc lfs_fifoop_opv_desc = 18053533Sheideman { &lfs_fifoop_p, lfs_fifoop_entries }; 18151558Smckusick #endif /* FIFO */ 18251558Smckusick 18337Sbill /* 18439608Smckusick * Vnode op for reading. 18539608Smckusick */ 18637737Smckusick /* ARGSUSED */ 187*54030Smckusick lfs_read(ap) 18853533Sheideman struct vop_read_args *ap; 18939608Smckusick { 19053867Sheideman register struct uio *uio = ap->a_uio; 19153593Sheideman register struct inode *ip = VTOI(ap->a_vp); 19251502Sbostic register struct lfs *fs; /* LFS */ 19339608Smckusick struct buf *bp; 19439608Smckusick daddr_t lbn, bn, rablock; 19553233Smckusick int size, error = 0; 19639608Smckusick long n, on, type; 19753233Smckusick off_t diff; 19839608Smckusick 19951852Sbostic #ifdef VERBOSE 20051852Sbostic printf("lfs_read: ino %d\n", ip->i_number); 20151852Sbostic #endif 20248039Smckusick #ifdef DIAGNOSTIC 20353867Sheideman if (uio->uio_rw != UIO_READ) 20439608Smckusick panic("ufs_read mode"); 20539608Smckusick type = ip->i_mode & IFMT; 20639608Smckusick if (type != IFDIR && type != IFREG && type != IFLNK) 20739608Smckusick panic("ufs_read type"); 20848039Smckusick #endif 20953867Sheideman if (uio->uio_resid == 0) 21039608Smckusick return (0); 21153867Sheideman if (uio->uio_offset < 0) 21239608Smckusick return (EINVAL); 21339608Smckusick ip->i_flag |= IACC; 21451155Sbostic 21551155Sbostic fs = ip->i_lfs; /* LFS */ 21639608Smckusick do { 21753867Sheideman lbn = lblkno(fs, uio->uio_offset); 21853867Sheideman on = blkoff(fs, uio->uio_offset); 21953867Sheideman n = MIN((unsigned)(fs->lfs_bsize - on), uio->uio_resid); 22053867Sheideman diff = ip->i_size - uio->uio_offset; 22139608Smckusick if (diff <= 0) 22239608Smckusick return (0); 22339608Smckusick if (diff < n) 22439608Smckusick n = diff; 22551155Sbostic size = blksize(fs); /* LFS */ 22639674Smckusick rablock = lbn + 1; 22753593Sheideman if (ap->a_vp->v_lastr + 1 == lbn && 22839896Smckusick lblktosize(fs, rablock) < ip->i_size) 22952195Smckusick error = breadn(ITOV(ip), lbn, size, &rablock, 23052195Smckusick &size, 1, NOCRED, &bp); 23139608Smckusick else 23239674Smckusick error = bread(ITOV(ip), lbn, size, NOCRED, &bp); 23353593Sheideman ap->a_vp->v_lastr = lbn; 23439608Smckusick n = MIN(n, size - bp->b_resid); 23539608Smckusick if (error) { 23639608Smckusick brelse(bp); 23739608Smckusick return (error); 23839608Smckusick } 23953867Sheideman error = uiomove(bp->b_un.b_addr + on, (int)n, uio); 24053867Sheideman if (n + on == fs->lfs_bsize || uio->uio_offset == ip->i_size) 24139608Smckusick bp->b_flags |= B_AGE; 24239608Smckusick brelse(bp); 24353867Sheideman } while (error == 0 && uio->uio_resid > 0 && n != 0); 24439608Smckusick return (error); 24539608Smckusick } 24639608Smckusick 24739608Smckusick /* 24839608Smckusick * Vnode op for writing. 24939608Smckusick */ 250*54030Smckusick lfs_write(ap) 25153533Sheideman struct vop_write_args *ap; 25239608Smckusick { 25353533Sheideman USES_VOP_TRUNCATE; 25453533Sheideman USES_VOP_UPDATE; 25553867Sheideman register struct vnode *vp = ap->a_vp; 256*54030Smckusick register struct uio *uio = ap->a_uio; 257*54030Smckusick struct proc *p = uio->uio_procp; 25853867Sheideman register struct inode *ip = VTOI(vp); 25952091Sbostic register struct lfs *fs; 260*54030Smckusick register ioflag = ap->a_ioflag; 26139608Smckusick struct buf *bp; 26252091Sbostic daddr_t lbn; 26353233Smckusick off_t osize; 26452091Sbostic int n, on, flags, newblock; 26545722Smckusick int size, resid, error = 0; 26639608Smckusick 26751852Sbostic #ifdef VERBOSE 26851852Sbostic printf("lfs_write ino %d\n", ip->i_number); 26951852Sbostic #endif 27048039Smckusick #ifdef DIAGNOSTIC 271*54030Smckusick if (uio->uio_rw != UIO_WRITE) 27252091Sbostic panic("lfs_write mode"); 27348039Smckusick #endif 27453867Sheideman switch (vp->v_type) { 27539608Smckusick case VREG: 276*54030Smckusick if (ioflag & IO_APPEND) 277*54030Smckusick uio->uio_offset = ip->i_size; 27839608Smckusick /* fall through */ 27939608Smckusick case VLNK: 28039608Smckusick break; 28139608Smckusick 28239608Smckusick case VDIR: 28352091Sbostic /* XXX This may not be correct for LFS. */ 284*54030Smckusick if ((ioflag & IO_SYNC) == 0) 28552091Sbostic panic("lfs_write nonsync dir write"); 28639608Smckusick break; 28739608Smckusick 28839608Smckusick default: 28952091Sbostic panic("lfs_write type"); 29039608Smckusick } 291*54030Smckusick if (uio->uio_offset < 0) 29239608Smckusick return (EINVAL); 293*54030Smckusick if (uio->uio_resid == 0) 29439608Smckusick return (0); 29539608Smckusick /* 29639608Smckusick * Maybe this should be above the vnode op call, but so long as 29739608Smckusick * file servers have no limits, i don't think it matters 29839608Smckusick */ 29953867Sheideman if (vp->v_type == VREG && p && 300*54030Smckusick uio->uio_offset + uio->uio_resid > 30147571Skarels p->p_rlimit[RLIMIT_FSIZE].rlim_cur) { 30247571Skarels psignal(p, SIGXFSZ); 30339608Smckusick return (EFBIG); 30439608Smckusick } 305*54030Smckusick resid = uio->uio_resid; 30639608Smckusick osize = ip->i_size; 30751183Sbostic fs = ip->i_lfs; /* LFS */ 30839674Smckusick flags = 0; 30951183Sbostic #ifdef NOTLFS 310*54030Smckusick if (ioflag & IO_SYNC) 31139674Smckusick flags = B_SYNC; 31251183Sbostic #endif 31339608Smckusick do { 314*54030Smckusick lbn = lblkno(fs, uio->uio_offset); 315*54030Smckusick on = blkoff(fs, uio->uio_offset); 316*54030Smckusick n = MIN((unsigned)(fs->lfs_bsize - on), uio->uio_resid); 31753867Sheideman if (error = lfs_balloc(vp, n, lbn, &bp)) 31839608Smckusick break; 319*54030Smckusick if (uio->uio_offset + n > ip->i_size) { 320*54030Smckusick ip->i_size = uio->uio_offset + n; 32153867Sheideman vnode_pager_setsize(vp, (u_long)ip->i_size); 32245722Smckusick } 32351183Sbostic size = blksize(fs); 32453867Sheideman (void) vnode_pager_uncache(vp); 32539608Smckusick n = MIN(n, size - bp->b_resid); 326*54030Smckusick error = uiomove(bp->b_un.b_addr + on, n, uio); 32751183Sbostic #ifdef NOTLFS /* LFS */ 328*54030Smckusick if (ioflag & IO_SYNC) 32939608Smckusick (void) bwrite(bp); 33039608Smckusick else if (n + on == fs->fs_bsize) { 33139608Smckusick bp->b_flags |= B_AGE; 33239608Smckusick bawrite(bp); 33339608Smckusick } else 33439608Smckusick bdwrite(bp); 33552091Sbostic ip->i_flag |= IUPD|ICHG; 33651183Sbostic #else 33752091Sbostic /* XXX This doesn't handle IO_SYNC. */ 33852091Sbostic LFS_UBWRITE(bp); 33951183Sbostic #endif 34053593Sheideman if (ap->a_cred->cr_uid != 0) 34139608Smckusick ip->i_mode &= ~(ISUID|ISGID); 342*54030Smckusick } while (error == 0 && uio->uio_resid > 0 && n != 0); 343*54030Smckusick if (error && (ioflag & IO_UNIT)) { 344*54030Smckusick (void)VOP_TRUNCATE(vp, osize, ioflag & IO_SYNC, ap->a_cred); 345*54030Smckusick uio->uio_offset -= resid - uio->uio_resid; 346*54030Smckusick uio->uio_resid = resid; 34739608Smckusick } 348*54030Smckusick if (!error && (ioflag & IO_SYNC)) 34953867Sheideman error = VOP_UPDATE(vp, &time, &time, 1); 35039608Smckusick return (error); 35139608Smckusick } 35239608Smckusick 3539167Ssam /* 35437737Smckusick * Synch an open file. 3559167Ssam */ 35637737Smckusick /* ARGSUSED */ 357*54030Smckusick lfs_fsync(ap) 35853533Sheideman struct vop_fsync_args *ap; 3597701Ssam { 36053533Sheideman USES_VOP_UPDATE; 36151852Sbostic struct inode *ip; 3627701Ssam 36351852Sbostic #ifdef VERBOSE 36451852Sbostic printf("lfs_fsync\n"); 36551852Sbostic #endif 36653593Sheideman ip = VTOI(ap->a_vp); 36753593Sheideman if (ap->a_fflags & FWRITE) 36837737Smckusick ip->i_flag |= ICHG; 36953593Sheideman return (VOP_UPDATE(ap->a_vp, &time, &time, ap->a_waitfor == MNT_WAIT)); 37037737Smckusick } 37151558Smckusick 37251558Smckusick /* 37351558Smckusick * Last reference to an inode, write the inode out and if necessary, 37451558Smckusick * truncate and deallocate the file. 37551558Smckusick */ 37651558Smckusick int 377*54030Smckusick lfs_inactive(ap) 37853533Sheideman struct vop_inactive_args *ap; 37951558Smckusick { 38053533Sheideman USES_VOP_TRUNCATE; 38153533Sheideman USES_VOP_UPDATE; 38253533Sheideman USES_VOP_VFREE; 38351852Sbostic extern int prtactive; 384*54030Smckusick register struct vnode *vp = ap->a_vp; 38551558Smckusick register struct inode *ip; 38651558Smckusick int mode, error; 38751558Smckusick 38851852Sbostic #ifdef VERBOSE 38951852Sbostic printf("lfs_inactive\n"); 39051852Sbostic #endif 391*54030Smckusick if (prtactive && vp->v_usecount != 0) 392*54030Smckusick vprint("lfs_inactive: pushing active", vp); 39351558Smckusick 39451558Smckusick /* Get rid of inodes related to stale file handles. */ 395*54030Smckusick ip = VTOI(vp); 39651558Smckusick if (ip->i_mode == 0) { 397*54030Smckusick if ((vp->v_flag & VXLOCK) == 0) 398*54030Smckusick vgone(vp); 39951558Smckusick return (0); 40051558Smckusick } 40151558Smckusick 40251558Smckusick error = 0; 40351558Smckusick ILOCK(ip); 404*54030Smckusick if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 40551558Smckusick #ifdef QUOTA 40651558Smckusick if (!getinoquota(ip)) 40751558Smckusick (void)chkiq(ip, -1, NOCRED, 0); 40851558Smckusick #endif 409*54030Smckusick error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED); 41051558Smckusick mode = ip->i_mode; 41151558Smckusick ip->i_mode = 0; 41251558Smckusick ip->i_rdev = 0; 41351558Smckusick ip->i_flag |= IUPD|ICHG; 414*54030Smckusick VOP_VFREE(vp, ip->i_number, mode); 41551558Smckusick } 41651558Smckusick if (ip->i_flag&(IUPD|IACC|ICHG|IMOD)) 417*54030Smckusick VOP_UPDATE(vp, &time, &time, 0); 41851558Smckusick IUNLOCK(ip); 41951558Smckusick ip->i_flag = 0; 42051558Smckusick /* 42151558Smckusick * If we are done with the inode, reclaim it 42251558Smckusick * so that it can be reused immediately. 42351558Smckusick */ 424*54030Smckusick if (vp->v_usecount == 0 && ip->i_mode == 0) 425*54030Smckusick vgone(vp); 42651558Smckusick return (error); 42751558Smckusick } 428