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*53533Sheideman * @(#)lfs_vnops.c 7.81 (Berkeley) 05/14/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. */ 37*53533Sheideman int (**lfs_vnodeop_p)(); 38*53533Sheideman struct vnodeopv_entry_desc lfs_vnodeop_entries[] = { 39*53533Sheideman { &vop_default_desc, vn_default_error }, 40*53533Sheideman { &vop_lookup_desc, ufs_lookup }, /* lookup */ 41*53533Sheideman { &vop_create_desc, ufs_create }, /* create */ 42*53533Sheideman { &vop_mknod_desc, ufs_mknod }, /* mknod */ 43*53533Sheideman { &vop_open_desc, ufs_open }, /* open */ 44*53533Sheideman { &vop_close_desc, ufs_close }, /* close */ 45*53533Sheideman { &vop_access_desc, ufs_access }, /* access */ 46*53533Sheideman { &vop_getattr_desc, ufs_getattr }, /* getattr */ 47*53533Sheideman { &vop_setattr_desc, ufs_setattr }, /* setattr */ 48*53533Sheideman { &vop_read_desc, lfs_read }, /* read */ 49*53533Sheideman { &vop_write_desc, lfs_write }, /* write */ 50*53533Sheideman { &vop_ioctl_desc, ufs_ioctl }, /* ioctl */ 51*53533Sheideman { &vop_select_desc, ufs_select }, /* select */ 52*53533Sheideman { &vop_mmap_desc, ufs_mmap }, /* mmap */ 53*53533Sheideman { &vop_fsync_desc, lfs_fsync }, /* fsync */ 54*53533Sheideman { &vop_seek_desc, ufs_seek }, /* seek */ 55*53533Sheideman { &vop_remove_desc, ufs_remove }, /* remove */ 56*53533Sheideman { &vop_link_desc, ufs_link }, /* link */ 57*53533Sheideman { &vop_rename_desc, ufs_rename }, /* rename */ 58*53533Sheideman { &vop_mkdir_desc, ufs_mkdir }, /* mkdir */ 59*53533Sheideman { &vop_rmdir_desc, ufs_rmdir }, /* rmdir */ 60*53533Sheideman { &vop_symlink_desc, ufs_symlink }, /* symlink */ 61*53533Sheideman { &vop_readdir_desc, ufs_readdir }, /* readdir */ 62*53533Sheideman { &vop_readlink_desc, ufs_readlink }, /* readlink */ 63*53533Sheideman { &vop_abortop_desc, ufs_abortop }, /* abortop */ 64*53533Sheideman { &vop_inactive_desc, lfs_inactive }, /* inactive */ 65*53533Sheideman { &vop_reclaim_desc, ufs_reclaim }, /* reclaim */ 66*53533Sheideman { &vop_lock_desc, ufs_lock }, /* lock */ 67*53533Sheideman { &vop_unlock_desc, ufs_unlock }, /* unlock */ 68*53533Sheideman { &vop_bmap_desc, lfs_bmap }, /* bmap */ 69*53533Sheideman { &vop_strategy_desc, ufs_strategy }, /* strategy */ 70*53533Sheideman { &vop_print_desc, ufs_print }, /* print */ 71*53533Sheideman { &vop_islocked_desc, ufs_islocked }, /* islocked */ 72*53533Sheideman { &vop_advlock_desc, ufs_advlock }, /* advlock */ 73*53533Sheideman { &vop_blkatoff_desc, lfs_blkatoff }, /* blkatoff */ 74*53533Sheideman { &vop_vget_desc, lfs_vget }, /* vget */ 75*53533Sheideman { &vop_valloc_desc, lfs_valloc }, /* valloc */ 76*53533Sheideman { &vop_vfree_desc, lfs_vfree }, /* vfree */ 77*53533Sheideman { &vop_truncate_desc, lfs_truncate }, /* truncate */ 78*53533Sheideman { &vop_update_desc, lfs_update }, /* update */ 79*53533Sheideman { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */ 80*53533Sheideman { (struct vnodeop_desc*)NULL, (int(*)())NULL } 8151482Sbostic }; 82*53533Sheideman struct vnodeopv_desc lfs_vnodeop_opv_desc = 83*53533Sheideman { &lfs_vnodeop_p, lfs_vnodeop_entries }; 846254Sroot 85*53533Sheideman int (**lfs_specop_p)(); 86*53533Sheideman struct vnodeopv_entry_desc lfs_specop_entries[] = { 87*53533Sheideman { &vop_default_desc, vn_default_error }, 88*53533Sheideman { &vop_lookup_desc, spec_lookup }, /* lookup */ 89*53533Sheideman { &vop_create_desc, spec_create }, /* create */ 90*53533Sheideman { &vop_mknod_desc, spec_mknod }, /* mknod */ 91*53533Sheideman { &vop_open_desc, spec_open }, /* open */ 92*53533Sheideman { &vop_close_desc, ufsspec_close }, /* close */ 93*53533Sheideman { &vop_access_desc, ufs_access }, /* access */ 94*53533Sheideman { &vop_getattr_desc, ufs_getattr }, /* getattr */ 95*53533Sheideman { &vop_setattr_desc, ufs_setattr }, /* setattr */ 96*53533Sheideman { &vop_read_desc, ufsspec_read }, /* read */ 97*53533Sheideman { &vop_write_desc, ufsspec_write }, /* write */ 98*53533Sheideman { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ 99*53533Sheideman { &vop_select_desc, spec_select }, /* select */ 100*53533Sheideman { &vop_mmap_desc, spec_mmap }, /* mmap */ 101*53533Sheideman { &vop_fsync_desc, spec_fsync }, /* fsync */ 102*53533Sheideman { &vop_seek_desc, spec_seek }, /* seek */ 103*53533Sheideman { &vop_remove_desc, spec_remove }, /* remove */ 104*53533Sheideman { &vop_link_desc, spec_link }, /* link */ 105*53533Sheideman { &vop_rename_desc, spec_rename }, /* rename */ 106*53533Sheideman { &vop_mkdir_desc, spec_mkdir }, /* mkdir */ 107*53533Sheideman { &vop_rmdir_desc, spec_rmdir }, /* rmdir */ 108*53533Sheideman { &vop_symlink_desc, spec_symlink }, /* symlink */ 109*53533Sheideman { &vop_readdir_desc, spec_readdir }, /* readdir */ 110*53533Sheideman { &vop_readlink_desc, spec_readlink }, /* readlink */ 111*53533Sheideman { &vop_abortop_desc, spec_abortop }, /* abortop */ 112*53533Sheideman { &vop_inactive_desc, lfs_inactive }, /* inactive */ 113*53533Sheideman { &vop_reclaim_desc, ufs_reclaim }, /* reclaim */ 114*53533Sheideman { &vop_lock_desc, ufs_lock }, /* lock */ 115*53533Sheideman { &vop_unlock_desc, ufs_unlock }, /* unlock */ 116*53533Sheideman { &vop_bmap_desc, spec_bmap }, /* bmap */ 117*53533Sheideman { &vop_strategy_desc, spec_strategy }, /* strategy */ 118*53533Sheideman { &vop_print_desc, ufs_print }, /* print */ 119*53533Sheideman { &vop_islocked_desc, ufs_islocked }, /* islocked */ 120*53533Sheideman { &vop_advlock_desc, spec_advlock }, /* advlock */ 121*53533Sheideman { &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */ 122*53533Sheideman { &vop_vget_desc, spec_vget }, /* vget */ 123*53533Sheideman { &vop_valloc_desc, spec_valloc }, /* valloc */ 124*53533Sheideman { &vop_vfree_desc, spec_vfree }, /* vfree */ 125*53533Sheideman { &vop_truncate_desc, spec_truncate }, /* truncate */ 126*53533Sheideman { &vop_update_desc, lfs_update }, /* update */ 127*53533Sheideman { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */ 128*53533Sheideman { (struct vnodeop_desc*)NULL, (int(*)())NULL } 12951558Smckusick }; 130*53533Sheideman struct vnodeopv_desc lfs_specop_opv_desc = 131*53533Sheideman { &lfs_specop_p, lfs_specop_entries }; 13251558Smckusick 13351558Smckusick #ifdef FIFO 134*53533Sheideman int (**lfs_fifoop_p)(); 135*53533Sheideman struct vnodeopv_entry_desc lfs_fifoop_entries[] = { 136*53533Sheideman { &vop_default_desc, vn_default_error }, 137*53533Sheideman { &vop_lookup_desc, fifo_lookup }, /* lookup */ 138*53533Sheideman { &vop_create_desc, fifo_create }, /* create */ 139*53533Sheideman { &vop_mknod_desc, fifo_mknod }, /* mknod */ 140*53533Sheideman { &vop_open_desc, fifo_open }, /* open */ 141*53533Sheideman { &vop_close_desc, ufsfifo_close }, /* close */ 142*53533Sheideman { &vop_access_desc, ufs_access }, /* access */ 143*53533Sheideman { &vop_getattr_desc, ufs_getattr }, /* getattr */ 144*53533Sheideman { &vop_setattr_desc, ufs_setattr }, /* setattr */ 145*53533Sheideman { &vop_read_desc, ufsfifo_read }, /* read */ 146*53533Sheideman { &vop_write_desc, ufsfifo_write }, /* write */ 147*53533Sheideman { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ 148*53533Sheideman { &vop_select_desc, fifo_select }, /* select */ 149*53533Sheideman { &vop_mmap_desc, fifo_mmap }, /* mmap */ 150*53533Sheideman { &vop_fsync_desc, fifo_fsync }, /* fsync */ 151*53533Sheideman { &vop_seek_desc, fifo_seek }, /* seek */ 152*53533Sheideman { &vop_remove_desc, fifo_remove }, /* remove */ 153*53533Sheideman { &vop_link_desc, fifo_link }, /* link */ 154*53533Sheideman { &vop_rename_desc, fifo_rename }, /* rename */ 155*53533Sheideman { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ 156*53533Sheideman { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ 157*53533Sheideman { &vop_symlink_desc, fifo_symlink }, /* symlink */ 158*53533Sheideman { &vop_readdir_desc, fifo_readdir }, /* readdir */ 159*53533Sheideman { &vop_readlink_desc, fifo_readlink }, /* readlink */ 160*53533Sheideman { &vop_abortop_desc, fifo_abortop }, /* abortop */ 161*53533Sheideman { &vop_inactive_desc, lfs_inactive }, /* inactive */ 162*53533Sheideman { &vop_reclaim_desc, ufs_reclaim }, /* reclaim */ 163*53533Sheideman { &vop_lock_desc, ufs_lock }, /* lock */ 164*53533Sheideman { &vop_unlock_desc, ufs_unlock }, /* unlock */ 165*53533Sheideman { &vop_bmap_desc, fifo_bmap }, /* bmap */ 166*53533Sheideman { &vop_strategy_desc, fifo_strategy }, /* strategy */ 167*53533Sheideman { &vop_print_desc, ufs_print }, /* print */ 168*53533Sheideman { &vop_islocked_desc, ufs_islocked }, /* islocked */ 169*53533Sheideman { &vop_advlock_desc, fifo_advlock }, /* advlock */ 170*53533Sheideman { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */ 171*53533Sheideman { &vop_vget_desc, fifo_vget }, /* vget */ 172*53533Sheideman { &vop_valloc_desc, fifo_valloc }, /* valloc */ 173*53533Sheideman { &vop_vfree_desc, fifo_vfree }, /* vfree */ 174*53533Sheideman { &vop_truncate_desc, fifo_truncate }, /* truncate */ 175*53533Sheideman { &vop_update_desc, lfs_update }, /* update */ 176*53533Sheideman { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */ 177*53533Sheideman { (struct vnodeop_desc*)NULL, (int(*)())NULL } 17851558Smckusick }; 179*53533Sheideman struct vnodeopv_desc lfs_fifoop_opv_desc = 180*53533Sheideman { &lfs_fifoop_p, lfs_fifoop_entries }; 18151558Smckusick #endif /* FIFO */ 18251558Smckusick 18337Sbill /* 18439608Smckusick * Vnode op for reading. 18539608Smckusick */ 18637737Smckusick /* ARGSUSED */ 187*53533Sheideman lfs_read (ap) 188*53533Sheideman struct vop_read_args *ap; 189*53533Sheideman #define vp (ap->a_vp) 190*53533Sheideman #define uio (ap->a_uio) 191*53533Sheideman #define ioflag (ap->a_ioflag) 192*53533Sheideman #define cred (ap->a_cred) 19339608Smckusick { 19439608Smckusick register struct inode *ip = VTOI(vp); 19551502Sbostic register struct lfs *fs; /* LFS */ 19639608Smckusick struct buf *bp; 19739608Smckusick daddr_t lbn, bn, rablock; 19853233Smckusick int size, error = 0; 19939608Smckusick long n, on, type; 20053233Smckusick off_t diff; 20139608Smckusick 20251852Sbostic #ifdef VERBOSE 20351852Sbostic printf("lfs_read: ino %d\n", ip->i_number); 20451852Sbostic #endif 20548039Smckusick #ifdef DIAGNOSTIC 20639608Smckusick if (uio->uio_rw != UIO_READ) 20739608Smckusick panic("ufs_read mode"); 20839608Smckusick type = ip->i_mode & IFMT; 20939608Smckusick if (type != IFDIR && type != IFREG && type != IFLNK) 21039608Smckusick panic("ufs_read type"); 21148039Smckusick #endif 21239608Smckusick if (uio->uio_resid == 0) 21339608Smckusick return (0); 21439608Smckusick if (uio->uio_offset < 0) 21539608Smckusick return (EINVAL); 21639608Smckusick ip->i_flag |= IACC; 21751155Sbostic 21851155Sbostic fs = ip->i_lfs; /* LFS */ 21939608Smckusick do { 22039608Smckusick lbn = lblkno(fs, uio->uio_offset); 22139608Smckusick on = blkoff(fs, uio->uio_offset); 22251155Sbostic n = MIN((unsigned)(fs->lfs_bsize - on), uio->uio_resid); 22339608Smckusick diff = ip->i_size - uio->uio_offset; 22439608Smckusick if (diff <= 0) 22539608Smckusick return (0); 22639608Smckusick if (diff < n) 22739608Smckusick n = diff; 22851155Sbostic size = blksize(fs); /* LFS */ 22939674Smckusick rablock = lbn + 1; 23039896Smckusick if (vp->v_lastr + 1 == lbn && 23139896Smckusick lblktosize(fs, rablock) < ip->i_size) 23252195Smckusick error = breadn(ITOV(ip), lbn, size, &rablock, 23352195Smckusick &size, 1, NOCRED, &bp); 23439608Smckusick else 23539674Smckusick error = bread(ITOV(ip), lbn, size, NOCRED, &bp); 23639815Smckusick vp->v_lastr = lbn; 23739608Smckusick n = MIN(n, size - bp->b_resid); 23839608Smckusick if (error) { 23939608Smckusick brelse(bp); 24039608Smckusick return (error); 24139608Smckusick } 24239608Smckusick error = uiomove(bp->b_un.b_addr + on, (int)n, uio); 24351155Sbostic if (n + on == fs->lfs_bsize || uio->uio_offset == ip->i_size) 24439608Smckusick bp->b_flags |= B_AGE; 24539608Smckusick brelse(bp); 24639608Smckusick } while (error == 0 && uio->uio_resid > 0 && n != 0); 24739608Smckusick return (error); 24839608Smckusick } 249*53533Sheideman #undef vp 250*53533Sheideman #undef uio 251*53533Sheideman #undef ioflag 252*53533Sheideman #undef cred 25339608Smckusick 25439608Smckusick /* 25539608Smckusick * Vnode op for writing. 25639608Smckusick */ 257*53533Sheideman lfs_write (ap) 258*53533Sheideman struct vop_write_args *ap; 259*53533Sheideman #define vp (ap->a_vp) 260*53533Sheideman #define uio (ap->a_uio) 261*53533Sheideman #define ioflag (ap->a_ioflag) 262*53533Sheideman #define cred (ap->a_cred) 26339608Smckusick { 264*53533Sheideman USES_VOP_TRUNCATE; 265*53533Sheideman USES_VOP_UPDATE; 26648039Smckusick struct proc *p = uio->uio_procp; 26739608Smckusick register struct inode *ip = VTOI(vp); 26852091Sbostic register struct lfs *fs; 26939608Smckusick struct buf *bp; 27052091Sbostic daddr_t lbn; 27153233Smckusick off_t osize; 27252091Sbostic int n, on, flags, newblock; 27345722Smckusick int size, resid, error = 0; 27439608Smckusick 27551852Sbostic #ifdef VERBOSE 27651852Sbostic printf("lfs_write ino %d\n", ip->i_number); 27751852Sbostic #endif 27848039Smckusick #ifdef DIAGNOSTIC 27939608Smckusick if (uio->uio_rw != UIO_WRITE) 28052091Sbostic panic("lfs_write mode"); 28148039Smckusick #endif 28239608Smckusick switch (vp->v_type) { 28339608Smckusick case VREG: 28439608Smckusick if (ioflag & IO_APPEND) 28539608Smckusick uio->uio_offset = ip->i_size; 28639608Smckusick /* fall through */ 28739608Smckusick case VLNK: 28839608Smckusick break; 28939608Smckusick 29039608Smckusick case VDIR: 29152091Sbostic /* XXX This may not be correct for LFS. */ 29239608Smckusick if ((ioflag & IO_SYNC) == 0) 29352091Sbostic panic("lfs_write nonsync dir write"); 29439608Smckusick break; 29539608Smckusick 29639608Smckusick default: 29752091Sbostic panic("lfs_write type"); 29839608Smckusick } 29939608Smckusick if (uio->uio_offset < 0) 30039608Smckusick return (EINVAL); 30139608Smckusick if (uio->uio_resid == 0) 30239608Smckusick return (0); 30339608Smckusick /* 30439608Smckusick * Maybe this should be above the vnode op call, but so long as 30539608Smckusick * file servers have no limits, i don't think it matters 30639608Smckusick */ 30749679Smckusick if (vp->v_type == VREG && p && 30839608Smckusick uio->uio_offset + uio->uio_resid > 30947571Skarels p->p_rlimit[RLIMIT_FSIZE].rlim_cur) { 31047571Skarels psignal(p, SIGXFSZ); 31139608Smckusick return (EFBIG); 31239608Smckusick } 31339608Smckusick resid = uio->uio_resid; 31439608Smckusick osize = ip->i_size; 31551183Sbostic fs = ip->i_lfs; /* LFS */ 31639674Smckusick flags = 0; 31751183Sbostic #ifdef NOTLFS 31839674Smckusick if (ioflag & IO_SYNC) 31939674Smckusick flags = B_SYNC; 32051183Sbostic #endif 32139608Smckusick do { 32239608Smckusick lbn = lblkno(fs, uio->uio_offset); 32351932Sbostic on = blkoff(fs, uio->uio_offset); 32451183Sbostic n = MIN((unsigned)(fs->lfs_bsize - on), uio->uio_resid); 32552091Sbostic if (error = lfs_balloc(vp, n, lbn, &bp)) 32639608Smckusick break; 32745722Smckusick if (uio->uio_offset + n > ip->i_size) { 32839608Smckusick ip->i_size = uio->uio_offset + n; 32952019Smckusick vnode_pager_setsize(vp, (u_long)ip->i_size); 33045722Smckusick } 33151183Sbostic size = blksize(fs); 33245722Smckusick (void) vnode_pager_uncache(vp); 33339608Smckusick n = MIN(n, size - bp->b_resid); 33439608Smckusick error = uiomove(bp->b_un.b_addr + on, n, uio); 33551183Sbostic #ifdef NOTLFS /* LFS */ 33639608Smckusick if (ioflag & IO_SYNC) 33739608Smckusick (void) bwrite(bp); 33839608Smckusick else if (n + on == fs->fs_bsize) { 33939608Smckusick bp->b_flags |= B_AGE; 34039608Smckusick bawrite(bp); 34139608Smckusick } else 34239608Smckusick bdwrite(bp); 34352091Sbostic ip->i_flag |= IUPD|ICHG; 34451183Sbostic #else 34552091Sbostic /* XXX This doesn't handle IO_SYNC. */ 34652091Sbostic LFS_UBWRITE(bp); 34751183Sbostic #endif 34839608Smckusick if (cred->cr_uid != 0) 34939608Smckusick ip->i_mode &= ~(ISUID|ISGID); 35039608Smckusick } while (error == 0 && uio->uio_resid > 0 && n != 0); 35139608Smckusick if (error && (ioflag & IO_UNIT)) { 352*53533Sheideman (void)VOP_TRUNCATE(vp, osize, ioflag & IO_SYNC, cred); 35339608Smckusick uio->uio_offset -= resid - uio->uio_resid; 35439608Smckusick uio->uio_resid = resid; 35539608Smckusick } 35642493Smckusick if (!error && (ioflag & IO_SYNC)) 357*53533Sheideman error = VOP_UPDATE(vp, &time, &time, 1); 35839608Smckusick return (error); 35939608Smckusick } 360*53533Sheideman #undef vp 361*53533Sheideman #undef uio 362*53533Sheideman #undef ioflag 363*53533Sheideman #undef cred 36439608Smckusick 3659167Ssam /* 36637737Smckusick * Synch an open file. 3679167Ssam */ 36837737Smckusick /* ARGSUSED */ 369*53533Sheideman lfs_fsync (ap) 370*53533Sheideman struct vop_fsync_args *ap; 371*53533Sheideman #define vp (ap->a_vp) 372*53533Sheideman #define fflags (ap->a_fflags) 373*53533Sheideman #define cred (ap->a_cred) 374*53533Sheideman #define waitfor (ap->a_waitfor) 375*53533Sheideman #define p (ap->a_p) 3767701Ssam { 377*53533Sheideman USES_VOP_UPDATE; 37851852Sbostic struct inode *ip; 3797701Ssam 38051852Sbostic #ifdef VERBOSE 38151852Sbostic printf("lfs_fsync\n"); 38251852Sbostic #endif 38351852Sbostic ip = VTOI(vp); 38448039Smckusick if (fflags & FWRITE) 38537737Smckusick ip->i_flag |= ICHG; 386*53533Sheideman return (VOP_UPDATE(vp, &time, &time, waitfor == MNT_WAIT)); 38737737Smckusick } 388*53533Sheideman #undef vp 389*53533Sheideman #undef fflags 390*53533Sheideman #undef cred 391*53533Sheideman #undef waitfor 392*53533Sheideman #undef p 39351558Smckusick 39451558Smckusick /* 39551558Smckusick * Last reference to an inode, write the inode out and if necessary, 39651558Smckusick * truncate and deallocate the file. 39751558Smckusick */ 39851558Smckusick int 399*53533Sheideman lfs_inactive (ap) 400*53533Sheideman struct vop_inactive_args *ap; 401*53533Sheideman #define vp (ap->a_vp) 402*53533Sheideman #define p (ap->a_p) 40351558Smckusick { 404*53533Sheideman USES_VOP_TRUNCATE; 405*53533Sheideman USES_VOP_UPDATE; 406*53533Sheideman USES_VOP_VFREE; 40751852Sbostic extern int prtactive; 40851558Smckusick register struct inode *ip; 40951558Smckusick int mode, error; 41051558Smckusick 41151852Sbostic #ifdef VERBOSE 41251852Sbostic printf("lfs_inactive\n"); 41351852Sbostic #endif 41451558Smckusick if (prtactive && vp->v_usecount != 0) 41551558Smckusick vprint("lfs_inactive: pushing active", vp); 41651558Smckusick 41751558Smckusick /* Get rid of inodes related to stale file handles. */ 41851558Smckusick ip = VTOI(vp); 41951558Smckusick if (ip->i_mode == 0) { 42051558Smckusick if ((vp->v_flag & VXLOCK) == 0) 42151558Smckusick vgone(vp); 42251558Smckusick return (0); 42351558Smckusick } 42451558Smckusick 42551558Smckusick error = 0; 42651558Smckusick ILOCK(ip); 42751558Smckusick if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 42851558Smckusick #ifdef QUOTA 42951558Smckusick if (!getinoquota(ip)) 43051558Smckusick (void)chkiq(ip, -1, NOCRED, 0); 43151558Smckusick #endif 432*53533Sheideman error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED); 43351558Smckusick mode = ip->i_mode; 43451558Smckusick ip->i_mode = 0; 43551558Smckusick ip->i_rdev = 0; 43651558Smckusick ip->i_flag |= IUPD|ICHG; 437*53533Sheideman VOP_VFREE(vp, ip->i_number, mode); 43851558Smckusick } 43951558Smckusick if (ip->i_flag&(IUPD|IACC|ICHG|IMOD)) 440*53533Sheideman VOP_UPDATE(vp, &time, &time, 0); 44151558Smckusick IUNLOCK(ip); 44251558Smckusick ip->i_flag = 0; 44351558Smckusick /* 44451558Smckusick * If we are done with the inode, reclaim it 44551558Smckusick * so that it can be reused immediately. 44651558Smckusick */ 44751558Smckusick if (vp->v_usecount == 0 && ip->i_mode == 0) 44851558Smckusick vgone(vp); 44951558Smckusick return (error); 45051558Smckusick } 451*53533Sheideman #undef vp 452*53533Sheideman #undef p 453