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*55460Sbostic * @(#)lfs_vnops.c 7.88 (Berkeley) 07/20/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/malloc.h> 2337Sbill 2453321Smckusick #include <vm/vm.h> 2553321Smckusick 26*55460Sbostic #include <miscfs/specfs/specdev.h> 27*55460Sbostic #include <miscfs/fifofs/fifo.h> 28*55460Sbostic 2951502Sbostic #include <ufs/ufs/quota.h> 3051502Sbostic #include <ufs/ufs/inode.h> 3151502Sbostic #include <ufs/ufs/dir.h> 3251502Sbostic #include <ufs/ufs/ufs_extern.h> 3347571Skarels 3451502Sbostic #include <ufs/lfs/lfs.h> 3551502Sbostic #include <ufs/lfs/lfs_extern.h> 3651134Sbostic 3751482Sbostic /* Global vfs data structures for lfs. */ 3853533Sheideman int (**lfs_vnodeop_p)(); 3953533Sheideman struct vnodeopv_entry_desc lfs_vnodeop_entries[] = { 4053533Sheideman { &vop_default_desc, vn_default_error }, 4153533Sheideman { &vop_lookup_desc, ufs_lookup }, /* lookup */ 4254264Sbostic { &vop_create_desc, lfs_create }, /* create */ 4354264Sbostic { &vop_mknod_desc, lfs_mknod }, /* mknod */ 4454030Smckusick { &vop_open_desc, ufs_open }, /* open */ 4554030Smckusick { &vop_close_desc, ufs_close }, /* close */ 4653533Sheideman { &vop_access_desc, ufs_access }, /* access */ 4753533Sheideman { &vop_getattr_desc, ufs_getattr }, /* getattr */ 4853533Sheideman { &vop_setattr_desc, ufs_setattr }, /* setattr */ 4954030Smckusick { &vop_read_desc, lfs_read }, /* read */ 5054030Smckusick { &vop_write_desc, lfs_write }, /* write */ 5154030Smckusick { &vop_ioctl_desc, ufs_ioctl }, /* ioctl */ 5253533Sheideman { &vop_select_desc, ufs_select }, /* select */ 5354030Smckusick { &vop_mmap_desc, ufs_mmap }, /* mmap */ 5454030Smckusick { &vop_fsync_desc, lfs_fsync }, /* fsync */ 5554030Smckusick { &vop_seek_desc, ufs_seek }, /* seek */ 5654264Sbostic { &vop_remove_desc, lfs_remove }, /* remove */ 5754264Sbostic { &vop_link_desc, lfs_link }, /* link */ 5854264Sbostic { &vop_rename_desc, lfs_rename }, /* rename */ 5954264Sbostic { &vop_mkdir_desc, lfs_mkdir }, /* mkdir */ 6054264Sbostic { &vop_rmdir_desc, lfs_rmdir }, /* rmdir */ 6154264Sbostic { &vop_symlink_desc, lfs_symlink }, /* symlink */ 6253533Sheideman { &vop_readdir_desc, ufs_readdir }, /* readdir */ 6353533Sheideman { &vop_readlink_desc, ufs_readlink }, /* readlink */ 6453533Sheideman { &vop_abortop_desc, ufs_abortop }, /* abortop */ 6553533Sheideman { &vop_inactive_desc, lfs_inactive }, /* inactive */ 6653533Sheideman { &vop_reclaim_desc, ufs_reclaim }, /* reclaim */ 6754030Smckusick { &vop_lock_desc, ufs_lock }, /* lock */ 6853533Sheideman { &vop_unlock_desc, ufs_unlock }, /* unlock */ 6954030Smckusick { &vop_bmap_desc, lfs_bmap }, /* bmap */ 7053533Sheideman { &vop_strategy_desc, ufs_strategy }, /* strategy */ 7154030Smckusick { &vop_print_desc, ufs_print }, /* print */ 7253533Sheideman { &vop_islocked_desc, ufs_islocked }, /* islocked */ 7353533Sheideman { &vop_advlock_desc, ufs_advlock }, /* advlock */ 7453533Sheideman { &vop_blkatoff_desc, lfs_blkatoff }, /* blkatoff */ 7553533Sheideman { &vop_valloc_desc, lfs_valloc }, /* valloc */ 7654030Smckusick { &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 */ 9154030Smckusick { &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 */ 10054030Smckusick { &vop_mmap_desc, spec_mmap }, /* mmap */ 10153533Sheideman { &vop_fsync_desc, spec_fsync }, /* fsync */ 10254030Smckusick { &vop_seek_desc, spec_seek }, /* seek */ 10353533Sheideman { &vop_remove_desc, spec_remove }, /* remove */ 10454030Smckusick { &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 */ 11454030Smckusick { &vop_lock_desc, ufs_lock }, /* lock */ 11553533Sheideman { &vop_unlock_desc, ufs_unlock }, /* unlock */ 11654030Smckusick { &vop_bmap_desc, spec_bmap }, /* bmap */ 11753533Sheideman { &vop_strategy_desc, spec_strategy }, /* strategy */ 11854030Smckusick { &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 */ 12253533Sheideman { &vop_valloc_desc, spec_valloc }, /* valloc */ 12354030Smckusick { &vop_vfree_desc, lfs_vfree }, /* vfree */ 12453533Sheideman { &vop_truncate_desc, spec_truncate }, /* truncate */ 12553533Sheideman { &vop_update_desc, lfs_update }, /* update */ 12653533Sheideman { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */ 12753533Sheideman { (struct vnodeop_desc*)NULL, (int(*)())NULL } 12851558Smckusick }; 12953533Sheideman struct vnodeopv_desc lfs_specop_opv_desc = 13053533Sheideman { &lfs_specop_p, lfs_specop_entries }; 13151558Smckusick 13251558Smckusick #ifdef FIFO 13353533Sheideman int (**lfs_fifoop_p)(); 13453533Sheideman struct vnodeopv_entry_desc lfs_fifoop_entries[] = { 13553533Sheideman { &vop_default_desc, vn_default_error }, 13653533Sheideman { &vop_lookup_desc, fifo_lookup }, /* lookup */ 13753533Sheideman { &vop_create_desc, fifo_create }, /* create */ 13853533Sheideman { &vop_mknod_desc, fifo_mknod }, /* mknod */ 13954030Smckusick { &vop_open_desc, fifo_open }, /* open */ 14053533Sheideman { &vop_close_desc, ufsfifo_close }, /* close */ 14153533Sheideman { &vop_access_desc, ufs_access }, /* access */ 14253533Sheideman { &vop_getattr_desc, ufs_getattr }, /* getattr */ 14353533Sheideman { &vop_setattr_desc, ufs_setattr }, /* setattr */ 14453533Sheideman { &vop_read_desc, ufsfifo_read }, /* read */ 14553533Sheideman { &vop_write_desc, ufsfifo_write }, /* write */ 14653533Sheideman { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ 14753533Sheideman { &vop_select_desc, fifo_select }, /* select */ 14854030Smckusick { &vop_mmap_desc, fifo_mmap }, /* mmap */ 14953533Sheideman { &vop_fsync_desc, fifo_fsync }, /* fsync */ 15054030Smckusick { &vop_seek_desc, fifo_seek }, /* seek */ 15153533Sheideman { &vop_remove_desc, fifo_remove }, /* remove */ 15254030Smckusick { &vop_link_desc, fifo_link }, /* link */ 15353533Sheideman { &vop_rename_desc, fifo_rename }, /* rename */ 15453533Sheideman { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ 15553533Sheideman { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ 15653533Sheideman { &vop_symlink_desc, fifo_symlink }, /* symlink */ 15753533Sheideman { &vop_readdir_desc, fifo_readdir }, /* readdir */ 15853533Sheideman { &vop_readlink_desc, fifo_readlink }, /* readlink */ 15953533Sheideman { &vop_abortop_desc, fifo_abortop }, /* abortop */ 16053533Sheideman { &vop_inactive_desc, lfs_inactive }, /* inactive */ 16153533Sheideman { &vop_reclaim_desc, ufs_reclaim }, /* reclaim */ 16254030Smckusick { &vop_lock_desc, ufs_lock }, /* lock */ 16353533Sheideman { &vop_unlock_desc, ufs_unlock }, /* unlock */ 16454030Smckusick { &vop_bmap_desc, fifo_bmap }, /* bmap */ 16553533Sheideman { &vop_strategy_desc, fifo_strategy }, /* strategy */ 16654030Smckusick { &vop_print_desc, ufs_print }, /* print */ 16753533Sheideman { &vop_islocked_desc, ufs_islocked }, /* islocked */ 16853533Sheideman { &vop_advlock_desc, fifo_advlock }, /* advlock */ 16953533Sheideman { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */ 17053533Sheideman { &vop_valloc_desc, fifo_valloc }, /* valloc */ 17154030Smckusick { &vop_vfree_desc, lfs_vfree }, /* vfree */ 17253533Sheideman { &vop_truncate_desc, fifo_truncate }, /* truncate */ 17353533Sheideman { &vop_update_desc, lfs_update }, /* update */ 17453533Sheideman { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */ 17553533Sheideman { (struct vnodeop_desc*)NULL, (int(*)())NULL } 17651558Smckusick }; 17753533Sheideman struct vnodeopv_desc lfs_fifoop_opv_desc = 17853533Sheideman { &lfs_fifoop_p, lfs_fifoop_entries }; 17951558Smckusick #endif /* FIFO */ 18051558Smckusick 18137Sbill /* 18239608Smckusick * Vnode op for reading. 18339608Smckusick */ 18437737Smckusick /* ARGSUSED */ 18554030Smckusick lfs_read(ap) 18654692Sbostic struct vop_read_args /* { 18754692Sbostic struct vnode *a_vp; 18854692Sbostic struct uio *a_uio; 18954692Sbostic int a_ioflag; 19054692Sbostic struct ucred *a_cred; 19154692Sbostic } */ *ap; 19239608Smckusick { 193*55460Sbostic register struct vnode *vp = ap->a_vp; 194*55460Sbostic register struct inode *ip = VTOI(vp); 19553867Sheideman register struct uio *uio = ap->a_uio; 196*55460Sbostic register struct lfs *fs; 19739608Smckusick struct buf *bp; 19839608Smckusick daddr_t lbn, bn, rablock; 19953233Smckusick off_t diff; 200*55460Sbostic int error = 0, size; 201*55460Sbostic long n, on; 20239608Smckusick 20348039Smckusick #ifdef DIAGNOSTIC 204*55460Sbostic int type; 20553867Sheideman if (uio->uio_rw != UIO_READ) 206*55460Sbostic panic("lfs_read mode"); 20739608Smckusick type = ip->i_mode & IFMT; 20839608Smckusick if (type != IFDIR && type != IFREG && type != IFLNK) 209*55460Sbostic panic("lfs_read type"); 210*55460Sbostic if (type == IFLNK && (int)ip->i_size < vp->v_mount->mnt_maxsymlinklen) 211*55460Sbostic panic("read short symlink"); 21248039Smckusick #endif 21353867Sheideman if (uio->uio_resid == 0) 21439608Smckusick return (0); 215*55460Sbostic fs = ip->i_lfs; 216*55460Sbostic if (uio->uio_offset < 0 || 217*55460Sbostic (u_quad_t)uio->uio_offset + uio->uio_resid > fs->lfs_maxfilesize) 218*55460Sbostic return (EFBIG); 21939608Smckusick ip->i_flag |= IACC; 22039608Smckusick do { 22153867Sheideman lbn = lblkno(fs, uio->uio_offset); 22253867Sheideman on = blkoff(fs, uio->uio_offset); 223*55460Sbostic n = min((unsigned)(fs->lfs_bsize - on), uio->uio_resid); 22453867Sheideman diff = ip->i_size - uio->uio_offset; 22539608Smckusick if (diff <= 0) 22639608Smckusick return (0); 22739608Smckusick if (diff < n) 22839608Smckusick n = diff; 229*55460Sbostic size = blksize(fs); 23039674Smckusick rablock = lbn + 1; 231*55460Sbostic if (vp->v_lastr + 1 == lbn && 23239896Smckusick lblktosize(fs, rablock) < ip->i_size) 23352195Smckusick error = breadn(ITOV(ip), lbn, size, &rablock, 23452195Smckusick &size, 1, NOCRED, &bp); 23539608Smckusick else 23639674Smckusick error = bread(ITOV(ip), lbn, size, NOCRED, &bp); 237*55460Sbostic vp->v_lastr = lbn; 238*55460Sbostic n = min(n, size - bp->b_resid); 23939608Smckusick if (error) { 24039608Smckusick brelse(bp); 24139608Smckusick return (error); 24239608Smckusick } 24353867Sheideman error = uiomove(bp->b_un.b_addr + on, (int)n, uio); 24453867Sheideman if (n + on == fs->lfs_bsize || uio->uio_offset == ip->i_size) 24539608Smckusick bp->b_flags |= B_AGE; 24639608Smckusick brelse(bp); 24753867Sheideman } while (error == 0 && uio->uio_resid > 0 && n != 0); 24839608Smckusick return (error); 24939608Smckusick } 25039608Smckusick 25139608Smckusick /* 25239608Smckusick * Vnode op for writing. 25339608Smckusick */ 25454030Smckusick lfs_write(ap) 25554692Sbostic struct vop_write_args /* { 25654692Sbostic struct vnode *a_vp; 25754692Sbostic struct uio *a_uio; 25854692Sbostic int a_ioflag; 25954692Sbostic struct ucred *a_cred; 26054692Sbostic } */ *ap; 26139608Smckusick { 26253867Sheideman register struct vnode *vp = ap->a_vp; 26354030Smckusick register struct uio *uio = ap->a_uio; 26454030Smckusick struct proc *p = uio->uio_procp; 26553867Sheideman register struct inode *ip = VTOI(vp); 26652091Sbostic register struct lfs *fs; 26754030Smckusick register ioflag = ap->a_ioflag; 26854765Smckusick struct timeval tv; 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 27548039Smckusick #ifdef DIAGNOSTIC 27654030Smckusick if (uio->uio_rw != UIO_WRITE) 27752091Sbostic panic("lfs_write mode"); 27848039Smckusick #endif 27953867Sheideman switch (vp->v_type) { 28039608Smckusick case VREG: 28154030Smckusick if (ioflag & IO_APPEND) 28254030Smckusick uio->uio_offset = ip->i_size; 28339608Smckusick /* fall through */ 28439608Smckusick case VLNK: 28539608Smckusick break; 28639608Smckusick 28739608Smckusick case VDIR: 28852091Sbostic /* XXX This may not be correct for LFS. */ 28954030Smckusick if ((ioflag & IO_SYNC) == 0) 29052091Sbostic panic("lfs_write nonsync dir write"); 29139608Smckusick break; 29239608Smckusick 29339608Smckusick default: 29452091Sbostic panic("lfs_write type"); 29539608Smckusick } 29654030Smckusick if (uio->uio_offset < 0) 29739608Smckusick return (EINVAL); 29854030Smckusick if (uio->uio_resid == 0) 29939608Smckusick return (0); 30039608Smckusick /* 30139608Smckusick * Maybe this should be above the vnode op call, but so long as 30239608Smckusick * file servers have no limits, i don't think it matters 30339608Smckusick */ 30453867Sheideman if (vp->v_type == VREG && p && 30554030Smckusick uio->uio_offset + uio->uio_resid > 30647571Skarels p->p_rlimit[RLIMIT_FSIZE].rlim_cur) { 30747571Skarels psignal(p, SIGXFSZ); 30839608Smckusick return (EFBIG); 30939608Smckusick } 31054030Smckusick resid = uio->uio_resid; 31139608Smckusick osize = ip->i_size; 31251183Sbostic fs = ip->i_lfs; /* LFS */ 313*55460Sbostic if (uio->uio_offset < 0 || 314*55460Sbostic (u_quad_t)uio->uio_offset + uio->uio_resid > fs->lfs_maxfilesize) 315*55460Sbostic return (EFBIG); 31639674Smckusick flags = 0; 31751183Sbostic #ifdef NOTLFS 31854030Smckusick if (ioflag & IO_SYNC) 31939674Smckusick flags = B_SYNC; 32051183Sbostic #endif 32139608Smckusick do { 32254030Smckusick lbn = lblkno(fs, uio->uio_offset); 32354030Smckusick on = blkoff(fs, uio->uio_offset); 324*55460Sbostic n = min((unsigned)(fs->lfs_bsize - on), uio->uio_resid); 32553867Sheideman if (error = lfs_balloc(vp, n, lbn, &bp)) 32639608Smckusick break; 32754030Smckusick if (uio->uio_offset + n > ip->i_size) { 32854030Smckusick ip->i_size = uio->uio_offset + n; 32953867Sheideman vnode_pager_setsize(vp, (u_long)ip->i_size); 33045722Smckusick } 33151183Sbostic size = blksize(fs); 33253867Sheideman (void) vnode_pager_uncache(vp); 333*55460Sbostic n = min(n, size - bp->b_resid); 33454030Smckusick error = uiomove(bp->b_un.b_addr + on, n, uio); 33551183Sbostic #ifdef NOTLFS /* LFS */ 33654030Smckusick 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 34853593Sheideman if (ap->a_cred->cr_uid != 0) 34939608Smckusick ip->i_mode &= ~(ISUID|ISGID); 35054030Smckusick } while (error == 0 && uio->uio_resid > 0 && n != 0); 35154030Smckusick if (error && (ioflag & IO_UNIT)) { 35254692Sbostic (void)VOP_TRUNCATE(vp, osize, ioflag & IO_SYNC, ap->a_cred, 35354692Sbostic uio->uio_procp); 35454030Smckusick uio->uio_offset -= resid - uio->uio_resid; 35554030Smckusick uio->uio_resid = resid; 35639608Smckusick } 35754765Smckusick if (!error && (ioflag & IO_SYNC)) { 35854765Smckusick tv = time; 35954765Smckusick error = VOP_UPDATE(vp, &tv, &tv, 1); 36054765Smckusick } 36139608Smckusick return (error); 36239608Smckusick } 36339608Smckusick 3649167Ssam /* 36537737Smckusick * Synch an open file. 3669167Ssam */ 36737737Smckusick /* ARGSUSED */ 36854030Smckusick lfs_fsync(ap) 36954692Sbostic struct vop_fsync_args /* { 37054692Sbostic struct vnode *a_vp; 37154692Sbostic struct ucred *a_cred; 37254692Sbostic int a_waitfor; 37354692Sbostic struct proc *a_p; 37454692Sbostic } */ *ap; 3757701Ssam { 37654765Smckusick struct timeval tv; 3777701Ssam 37851852Sbostic #ifdef VERBOSE 37951852Sbostic printf("lfs_fsync\n"); 38051852Sbostic #endif 38154765Smckusick tv = time; 38254765Smckusick return (VOP_UPDATE(ap->a_vp, &tv, &tv, ap->a_waitfor == MNT_WAIT)); 38337737Smckusick } 38451558Smckusick 38551558Smckusick /* 38651558Smckusick * Last reference to an inode, write the inode out and if necessary, 38751558Smckusick * truncate and deallocate the file. 38851558Smckusick */ 38951558Smckusick int 39054030Smckusick lfs_inactive(ap) 39154692Sbostic struct vop_inactive_args /* { 39254692Sbostic struct vnode *a_vp; 39354692Sbostic } */ *ap; 39451558Smckusick { 39551852Sbostic extern int prtactive; 39654030Smckusick register struct vnode *vp = ap->a_vp; 39751558Smckusick register struct inode *ip; 39854765Smckusick struct timeval tv; 39951558Smckusick int mode, error; 40051558Smckusick 40151852Sbostic #ifdef VERBOSE 40251852Sbostic printf("lfs_inactive\n"); 40351852Sbostic #endif 40454030Smckusick if (prtactive && vp->v_usecount != 0) 40554030Smckusick vprint("lfs_inactive: pushing active", vp); 40651558Smckusick 40751558Smckusick /* Get rid of inodes related to stale file handles. */ 40854030Smckusick ip = VTOI(vp); 40951558Smckusick if (ip->i_mode == 0) { 41054030Smckusick if ((vp->v_flag & VXLOCK) == 0) 41154030Smckusick vgone(vp); 41251558Smckusick return (0); 41351558Smckusick } 41451558Smckusick 41551558Smckusick error = 0; 41651558Smckusick ILOCK(ip); 41754030Smckusick if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 41851558Smckusick #ifdef QUOTA 41951558Smckusick if (!getinoquota(ip)) 42051558Smckusick (void)chkiq(ip, -1, NOCRED, 0); 42151558Smckusick #endif 42254692Sbostic error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, NULL); 42351558Smckusick mode = ip->i_mode; 42451558Smckusick ip->i_mode = 0; 42551558Smckusick ip->i_rdev = 0; 42651558Smckusick ip->i_flag |= IUPD|ICHG; 42754030Smckusick VOP_VFREE(vp, ip->i_number, mode); 42851558Smckusick } 42954765Smckusick if (ip->i_flag&(IUPD|IACC|ICHG|IMOD)) { 43054765Smckusick tv = time; 43154765Smckusick VOP_UPDATE(vp, &tv, &tv, 0); 43254765Smckusick } 43351558Smckusick IUNLOCK(ip); 43451558Smckusick ip->i_flag = 0; 43551558Smckusick /* 43651558Smckusick * If we are done with the inode, reclaim it 43751558Smckusick * so that it can be reused immediately. 43851558Smckusick */ 43954030Smckusick if (vp->v_usecount == 0 && ip->i_mode == 0) 44054030Smckusick vgone(vp); 44151558Smckusick return (error); 44251558Smckusick } 44354264Sbostic 44454264Sbostic /* 44554264Sbostic * These macros are used to bracket UFS directory ops, so that we can 44654264Sbostic * identify all the pages touched during directory ops which need to 44754264Sbostic * be ordered and flushed atomically, so that they may be recovered. 44854264Sbostic */ 44954264Sbostic #define SET_DIROP(fs) { \ 45054264Sbostic int __s; \ 45154264Sbostic __s = splbio(); \ 45254264Sbostic if ((fs)->lfs_writer) \ 45354264Sbostic tsleep(&(fs)->lfs_dirops, PRIBIO + 1, "lfs dirop", 0); \ 45454264Sbostic ++(fs)->lfs_dirops; \ 45554264Sbostic (fs)->lfs_doifile = 1; \ 45654264Sbostic splx(__s); \ 45754264Sbostic } 45854264Sbostic 45954264Sbostic #define SET_ENDOP(fs) { \ 46054264Sbostic int __s; \ 46154264Sbostic __s = splbio(); \ 46254264Sbostic --(fs)->lfs_dirops; \ 46354264Sbostic if (!(fs)->lfs_dirops) \ 46454264Sbostic wakeup(&(fs)->lfs_writer); \ 46554264Sbostic splx(__s); \ 46654264Sbostic } 46754264Sbostic 46854264Sbostic #define MARK_VNODE(dvp) (dvp)->v_flag |= VDIROP 46954264Sbostic 47054264Sbostic int 47154264Sbostic lfs_symlink(ap) 47254692Sbostic struct vop_symlink_args /* { 47354692Sbostic struct vnode *a_dvp; 47454692Sbostic struct vnode **a_vpp; 47554692Sbostic struct componentname *a_cnp; 47654692Sbostic struct vattr *a_vap; 47754692Sbostic char *a_target; 47854692Sbostic } */ *ap; 47954264Sbostic { 48054264Sbostic int ret; 48154264Sbostic 48254264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 48354264Sbostic MARK_VNODE(ap->a_dvp); 48454264Sbostic ret = ufs_symlink(ap); 48554264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 48654264Sbostic return (ret); 48754264Sbostic } 48854264Sbostic 48954264Sbostic int 49054264Sbostic lfs_mknod(ap) 49154692Sbostic struct vop_mknod_args /* { 49254692Sbostic struct vnode *a_dvp; 49354692Sbostic struct vnode **a_vpp; 49454692Sbostic struct componentname *a_cnp; 49554692Sbostic struct vattr *a_vap; 49654692Sbostic } */ *ap; 49754264Sbostic { 49854264Sbostic int ret; 49954264Sbostic 50054264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 50154264Sbostic MARK_VNODE(ap->a_dvp); 50254264Sbostic ret = ufs_mknod(ap); 50354264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 50454264Sbostic return (ret); 50554264Sbostic } 50654264Sbostic 50754264Sbostic int 50854264Sbostic lfs_create(ap) 50954692Sbostic struct vop_create_args /* { 51054692Sbostic struct vnode *a_dvp; 51154692Sbostic struct vnode **a_vpp; 51254692Sbostic struct componentname *a_cnp; 51354692Sbostic struct vattr *a_vap; 51454692Sbostic } */ *ap; 51554264Sbostic { 51654264Sbostic int ret; 51754264Sbostic 51854264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 51954264Sbostic MARK_VNODE(ap->a_dvp); 52054264Sbostic ret = ufs_create(ap); 52154264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 52254264Sbostic return (ret); 52354264Sbostic } 52454264Sbostic 52554264Sbostic int 52654264Sbostic lfs_mkdir(ap) 52754692Sbostic struct vop_mkdir_args /* { 52854692Sbostic struct vnode *a_dvp; 52954692Sbostic struct vnode **a_vpp; 53054692Sbostic struct componentname *a_cnp; 53154692Sbostic struct vattr *a_vap; 53254692Sbostic } */ *ap; 53354264Sbostic { 53454264Sbostic int ret; 53554264Sbostic 53654264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 53754264Sbostic MARK_VNODE(ap->a_dvp); 53854264Sbostic ret = ufs_mkdir(ap); 53954264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 54054264Sbostic return (ret); 54154264Sbostic } 54254264Sbostic 54354264Sbostic int 54454264Sbostic lfs_remove(ap) 54554692Sbostic struct vop_remove_args /* { 54654692Sbostic struct vnode *a_dvp; 54754692Sbostic struct vnode *a_vp; 54854692Sbostic struct componentname *a_cnp; 54954692Sbostic } */ *ap; 55054264Sbostic { 55154264Sbostic int ret; 55254264Sbostic 55354264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 55454264Sbostic MARK_VNODE(ap->a_dvp); 55554264Sbostic MARK_VNODE(ap->a_vp); 55654264Sbostic ret = ufs_remove(ap); 55754264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 55854264Sbostic return (ret); 55954264Sbostic } 56054264Sbostic 56154264Sbostic int 56254264Sbostic lfs_rmdir(ap) 56354692Sbostic struct vop_rmdir_args /* { 56454692Sbostic struct vnodeop_desc *a_desc; 56554692Sbostic struct vnode *a_dvp; 56654692Sbostic struct vnode *a_vp; 56754692Sbostic struct componentname *a_cnp; 56854692Sbostic } */ *ap; 56954264Sbostic { 57054264Sbostic int ret; 57154264Sbostic 57254264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 57354264Sbostic MARK_VNODE(ap->a_dvp); 57454264Sbostic MARK_VNODE(ap->a_vp); 57554264Sbostic ret = ufs_rmdir(ap); 57654264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 57754264Sbostic return (ret); 57854264Sbostic } 57954264Sbostic 58054264Sbostic int 58154264Sbostic lfs_link(ap) 58254692Sbostic struct vop_link_args /* { 58354692Sbostic struct vnode *a_vp; 58454692Sbostic struct vnode *a_tdvp; 58554692Sbostic struct componentname *a_cnp; 58654692Sbostic } */ *ap; 58754264Sbostic { 58854264Sbostic int ret; 58954264Sbostic 59054264Sbostic SET_DIROP(VTOI(ap->a_vp)->i_lfs); 59154264Sbostic MARK_VNODE(ap->a_vp); 59254264Sbostic ret = ufs_link(ap); 59354264Sbostic SET_ENDOP(VTOI(ap->a_vp)->i_lfs); 59454264Sbostic return (ret); 59554264Sbostic } 59654264Sbostic 59754264Sbostic int 59854264Sbostic lfs_rename(ap) 59954692Sbostic struct vop_rename_args /* { 60054692Sbostic struct vnode *a_fdvp; 60154692Sbostic struct vnode *a_fvp; 60254692Sbostic struct componentname *a_fcnp; 60354692Sbostic struct vnode *a_tdvp; 60454692Sbostic struct vnode *a_tvp; 60554692Sbostic struct componentname *a_tcnp; 60654692Sbostic } */ *ap; 60754264Sbostic { 60854264Sbostic int ret; 60954264Sbostic 61054264Sbostic SET_DIROP(VTOI(ap->a_fdvp)->i_lfs); 61154264Sbostic MARK_VNODE(ap->a_fdvp); 61254264Sbostic MARK_VNODE(ap->a_tdvp); 61354264Sbostic ret = ufs_rename(ap); 61454264Sbostic SET_ENDOP(VTOI(ap->a_fdvp)->i_lfs); 61554264Sbostic return (ret); 61654264Sbostic } 617