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*55547Sbostic * @(#)lfs_vnops.c 7.89 (Berkeley) 07/22/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 2655460Sbostic #include <miscfs/specfs/specdev.h> 2755460Sbostic #include <miscfs/fifofs/fifo.h> 2855460Sbostic 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 { 19355460Sbostic register struct vnode *vp = ap->a_vp; 19455460Sbostic register struct inode *ip = VTOI(vp); 19553867Sheideman register struct uio *uio = ap->a_uio; 19655460Sbostic register struct lfs *fs; 19739608Smckusick struct buf *bp; 19839608Smckusick daddr_t lbn, bn, rablock; 19953233Smckusick off_t diff; 20055460Sbostic int error = 0, size; 20155460Sbostic long n, on; 20239608Smckusick 20348039Smckusick #ifdef DIAGNOSTIC 20455460Sbostic int type; 20553867Sheideman if (uio->uio_rw != UIO_READ) 20655460Sbostic panic("lfs_read mode"); 20739608Smckusick type = ip->i_mode & IFMT; 20839608Smckusick if (type != IFDIR && type != IFREG && type != IFLNK) 20955460Sbostic panic("lfs_read type"); 21055460Sbostic if (type == IFLNK && (int)ip->i_size < vp->v_mount->mnt_maxsymlinklen) 21155460Sbostic panic("read short symlink"); 21248039Smckusick #endif 21353867Sheideman if (uio->uio_resid == 0) 21439608Smckusick return (0); 21555460Sbostic fs = ip->i_lfs; 21655460Sbostic if (uio->uio_offset < 0 || 21755460Sbostic (u_quad_t)uio->uio_offset + uio->uio_resid > fs->lfs_maxfilesize) 21855460Sbostic return (EFBIG); 21939608Smckusick ip->i_flag |= IACC; 22039608Smckusick do { 22153867Sheideman lbn = lblkno(fs, uio->uio_offset); 22253867Sheideman on = blkoff(fs, uio->uio_offset); 22355460Sbostic 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; 22955460Sbostic size = blksize(fs); 23039674Smckusick rablock = lbn + 1; 23155460Sbostic 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); 23755460Sbostic vp->v_lastr = lbn; 23855460Sbostic 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 */ 31355460Sbostic if (uio->uio_offset < 0 || 31455460Sbostic (u_quad_t)uio->uio_offset + uio->uio_resid > fs->lfs_maxfilesize) 31555460Sbostic 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); 32455460Sbostic 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); 33355460Sbostic 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; 382*55547Sbostic return (VOP_UPDATE(ap->a_vp, &tv, &tv, 383*55547Sbostic ap->a_waitfor == MNT_WAIT ? LFS_SYNC : 0)); 38437737Smckusick } 38551558Smckusick 38651558Smckusick /* 38751558Smckusick * Last reference to an inode, write the inode out and if necessary, 38851558Smckusick * truncate and deallocate the file. 38951558Smckusick */ 39051558Smckusick int 39154030Smckusick lfs_inactive(ap) 39254692Sbostic struct vop_inactive_args /* { 39354692Sbostic struct vnode *a_vp; 39454692Sbostic } */ *ap; 39551558Smckusick { 39651852Sbostic extern int prtactive; 39754030Smckusick register struct vnode *vp = ap->a_vp; 39851558Smckusick register struct inode *ip; 39954765Smckusick struct timeval tv; 40051558Smckusick int mode, error; 40151558Smckusick 40251852Sbostic #ifdef VERBOSE 40351852Sbostic printf("lfs_inactive\n"); 40451852Sbostic #endif 40554030Smckusick if (prtactive && vp->v_usecount != 0) 40654030Smckusick vprint("lfs_inactive: pushing active", vp); 40751558Smckusick 40851558Smckusick /* Get rid of inodes related to stale file handles. */ 40954030Smckusick ip = VTOI(vp); 41051558Smckusick if (ip->i_mode == 0) { 41154030Smckusick if ((vp->v_flag & VXLOCK) == 0) 41254030Smckusick vgone(vp); 41351558Smckusick return (0); 41451558Smckusick } 41551558Smckusick 41651558Smckusick error = 0; 41751558Smckusick ILOCK(ip); 41854030Smckusick if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 41951558Smckusick #ifdef QUOTA 42051558Smckusick if (!getinoquota(ip)) 42151558Smckusick (void)chkiq(ip, -1, NOCRED, 0); 42251558Smckusick #endif 42354692Sbostic error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, NULL); 42451558Smckusick mode = ip->i_mode; 42551558Smckusick ip->i_mode = 0; 42651558Smckusick ip->i_rdev = 0; 42751558Smckusick ip->i_flag |= IUPD|ICHG; 42854030Smckusick VOP_VFREE(vp, ip->i_number, mode); 42951558Smckusick } 43054765Smckusick if (ip->i_flag&(IUPD|IACC|ICHG|IMOD)) { 43154765Smckusick tv = time; 43254765Smckusick VOP_UPDATE(vp, &tv, &tv, 0); 43354765Smckusick } 43451558Smckusick IUNLOCK(ip); 43551558Smckusick ip->i_flag = 0; 43651558Smckusick /* 43751558Smckusick * If we are done with the inode, reclaim it 43851558Smckusick * so that it can be reused immediately. 43951558Smckusick */ 44054030Smckusick if (vp->v_usecount == 0 && ip->i_mode == 0) 44154030Smckusick vgone(vp); 44251558Smckusick return (error); 44351558Smckusick } 44454264Sbostic 44554264Sbostic /* 44654264Sbostic * These macros are used to bracket UFS directory ops, so that we can 44754264Sbostic * identify all the pages touched during directory ops which need to 44854264Sbostic * be ordered and flushed atomically, so that they may be recovered. 44954264Sbostic */ 45054264Sbostic #define SET_DIROP(fs) { \ 45154264Sbostic if ((fs)->lfs_writer) \ 452*55547Sbostic tsleep(&(fs)->lfs_dirops, PRIBIO + 1, "lfs_dirop", 0); \ 45354264Sbostic ++(fs)->lfs_dirops; \ 45454264Sbostic (fs)->lfs_doifile = 1; \ 45554264Sbostic } 45654264Sbostic 45754264Sbostic #define SET_ENDOP(fs) { \ 45854264Sbostic --(fs)->lfs_dirops; \ 45954264Sbostic if (!(fs)->lfs_dirops) \ 46054264Sbostic wakeup(&(fs)->lfs_writer); \ 46154264Sbostic } 46254264Sbostic 46354264Sbostic #define MARK_VNODE(dvp) (dvp)->v_flag |= VDIROP 46454264Sbostic 46554264Sbostic int 46654264Sbostic lfs_symlink(ap) 46754692Sbostic struct vop_symlink_args /* { 46854692Sbostic struct vnode *a_dvp; 46954692Sbostic struct vnode **a_vpp; 47054692Sbostic struct componentname *a_cnp; 47154692Sbostic struct vattr *a_vap; 47254692Sbostic char *a_target; 47354692Sbostic } */ *ap; 47454264Sbostic { 47554264Sbostic int ret; 47654264Sbostic 47754264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 47854264Sbostic MARK_VNODE(ap->a_dvp); 47954264Sbostic ret = ufs_symlink(ap); 48054264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 48154264Sbostic return (ret); 48254264Sbostic } 48354264Sbostic 48454264Sbostic int 48554264Sbostic lfs_mknod(ap) 48654692Sbostic struct vop_mknod_args /* { 48754692Sbostic struct vnode *a_dvp; 48854692Sbostic struct vnode **a_vpp; 48954692Sbostic struct componentname *a_cnp; 49054692Sbostic struct vattr *a_vap; 49154692Sbostic } */ *ap; 49254264Sbostic { 49354264Sbostic int ret; 49454264Sbostic 49554264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 49654264Sbostic MARK_VNODE(ap->a_dvp); 49754264Sbostic ret = ufs_mknod(ap); 49854264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 49954264Sbostic return (ret); 50054264Sbostic } 50154264Sbostic 50254264Sbostic int 50354264Sbostic lfs_create(ap) 50454692Sbostic struct vop_create_args /* { 50554692Sbostic struct vnode *a_dvp; 50654692Sbostic struct vnode **a_vpp; 50754692Sbostic struct componentname *a_cnp; 50854692Sbostic struct vattr *a_vap; 50954692Sbostic } */ *ap; 51054264Sbostic { 51154264Sbostic int ret; 51254264Sbostic 51354264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 51454264Sbostic MARK_VNODE(ap->a_dvp); 51554264Sbostic ret = ufs_create(ap); 51654264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 51754264Sbostic return (ret); 51854264Sbostic } 51954264Sbostic 52054264Sbostic int 52154264Sbostic lfs_mkdir(ap) 52254692Sbostic struct vop_mkdir_args /* { 52354692Sbostic struct vnode *a_dvp; 52454692Sbostic struct vnode **a_vpp; 52554692Sbostic struct componentname *a_cnp; 52654692Sbostic struct vattr *a_vap; 52754692Sbostic } */ *ap; 52854264Sbostic { 52954264Sbostic int ret; 53054264Sbostic 53154264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 53254264Sbostic MARK_VNODE(ap->a_dvp); 53354264Sbostic ret = ufs_mkdir(ap); 53454264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 53554264Sbostic return (ret); 53654264Sbostic } 53754264Sbostic 53854264Sbostic int 53954264Sbostic lfs_remove(ap) 54054692Sbostic struct vop_remove_args /* { 54154692Sbostic struct vnode *a_dvp; 54254692Sbostic struct vnode *a_vp; 54354692Sbostic struct componentname *a_cnp; 54454692Sbostic } */ *ap; 54554264Sbostic { 54654264Sbostic int ret; 54754264Sbostic 54854264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 54954264Sbostic MARK_VNODE(ap->a_dvp); 55054264Sbostic MARK_VNODE(ap->a_vp); 55154264Sbostic ret = ufs_remove(ap); 55254264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 55354264Sbostic return (ret); 55454264Sbostic } 55554264Sbostic 55654264Sbostic int 55754264Sbostic lfs_rmdir(ap) 55854692Sbostic struct vop_rmdir_args /* { 55954692Sbostic struct vnodeop_desc *a_desc; 56054692Sbostic struct vnode *a_dvp; 56154692Sbostic struct vnode *a_vp; 56254692Sbostic struct componentname *a_cnp; 56354692Sbostic } */ *ap; 56454264Sbostic { 56554264Sbostic int ret; 56654264Sbostic 56754264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 56854264Sbostic MARK_VNODE(ap->a_dvp); 56954264Sbostic MARK_VNODE(ap->a_vp); 57054264Sbostic ret = ufs_rmdir(ap); 57154264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 57254264Sbostic return (ret); 57354264Sbostic } 57454264Sbostic 57554264Sbostic int 57654264Sbostic lfs_link(ap) 57754692Sbostic struct vop_link_args /* { 57854692Sbostic struct vnode *a_vp; 57954692Sbostic struct vnode *a_tdvp; 58054692Sbostic struct componentname *a_cnp; 58154692Sbostic } */ *ap; 58254264Sbostic { 58354264Sbostic int ret; 58454264Sbostic 58554264Sbostic SET_DIROP(VTOI(ap->a_vp)->i_lfs); 58654264Sbostic MARK_VNODE(ap->a_vp); 58754264Sbostic ret = ufs_link(ap); 58854264Sbostic SET_ENDOP(VTOI(ap->a_vp)->i_lfs); 58954264Sbostic return (ret); 59054264Sbostic } 59154264Sbostic 59254264Sbostic int 59354264Sbostic lfs_rename(ap) 59454692Sbostic struct vop_rename_args /* { 59554692Sbostic struct vnode *a_fdvp; 59654692Sbostic struct vnode *a_fvp; 59754692Sbostic struct componentname *a_fcnp; 59854692Sbostic struct vnode *a_tdvp; 59954692Sbostic struct vnode *a_tvp; 60054692Sbostic struct componentname *a_tcnp; 60154692Sbostic } */ *ap; 60254264Sbostic { 60354264Sbostic int ret; 60454264Sbostic 60554264Sbostic SET_DIROP(VTOI(ap->a_fdvp)->i_lfs); 60654264Sbostic MARK_VNODE(ap->a_fdvp); 60754264Sbostic MARK_VNODE(ap->a_tdvp); 60854264Sbostic ret = ufs_rename(ap); 60954264Sbostic SET_ENDOP(VTOI(ap->a_fdvp)->i_lfs); 61054264Sbostic return (ret); 61154264Sbostic } 612