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*54765Smckusick * @(#)lfs_vnops.c 7.87 (Berkeley) 07/07/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 */ 4154264Sbostic { &vop_create_desc, lfs_create }, /* create */ 4254264Sbostic { &vop_mknod_desc, lfs_mknod }, /* mknod */ 4354030Smckusick { &vop_open_desc, ufs_open }, /* open */ 4454030Smckusick { &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 */ 4854030Smckusick { &vop_read_desc, lfs_read }, /* read */ 4954030Smckusick { &vop_write_desc, lfs_write }, /* write */ 5054030Smckusick { &vop_ioctl_desc, ufs_ioctl }, /* ioctl */ 5153533Sheideman { &vop_select_desc, ufs_select }, /* select */ 5254030Smckusick { &vop_mmap_desc, ufs_mmap }, /* mmap */ 5354030Smckusick { &vop_fsync_desc, lfs_fsync }, /* fsync */ 5454030Smckusick { &vop_seek_desc, ufs_seek }, /* seek */ 5554264Sbostic { &vop_remove_desc, lfs_remove }, /* remove */ 5654264Sbostic { &vop_link_desc, lfs_link }, /* link */ 5754264Sbostic { &vop_rename_desc, lfs_rename }, /* rename */ 5854264Sbostic { &vop_mkdir_desc, lfs_mkdir }, /* mkdir */ 5954264Sbostic { &vop_rmdir_desc, lfs_rmdir }, /* rmdir */ 6054264Sbostic { &vop_symlink_desc, lfs_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 */ 6654030Smckusick { &vop_lock_desc, ufs_lock }, /* lock */ 6753533Sheideman { &vop_unlock_desc, ufs_unlock }, /* unlock */ 6854030Smckusick { &vop_bmap_desc, lfs_bmap }, /* bmap */ 6953533Sheideman { &vop_strategy_desc, ufs_strategy }, /* strategy */ 7054030Smckusick { &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 */ 7453533Sheideman { &vop_valloc_desc, lfs_valloc }, /* valloc */ 7554030Smckusick { &vop_vfree_desc, lfs_vfree }, /* vfree */ 7653533Sheideman { &vop_truncate_desc, lfs_truncate }, /* truncate */ 7753533Sheideman { &vop_update_desc, lfs_update }, /* update */ 7853533Sheideman { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */ 7953533Sheideman { (struct vnodeop_desc*)NULL, (int(*)())NULL } 8051482Sbostic }; 8153533Sheideman struct vnodeopv_desc lfs_vnodeop_opv_desc = 8253533Sheideman { &lfs_vnodeop_p, lfs_vnodeop_entries }; 836254Sroot 8453533Sheideman int (**lfs_specop_p)(); 8553533Sheideman struct vnodeopv_entry_desc lfs_specop_entries[] = { 8653533Sheideman { &vop_default_desc, vn_default_error }, 8753533Sheideman { &vop_lookup_desc, spec_lookup }, /* lookup */ 8853533Sheideman { &vop_create_desc, spec_create }, /* create */ 8953533Sheideman { &vop_mknod_desc, spec_mknod }, /* mknod */ 9054030Smckusick { &vop_open_desc, spec_open }, /* open */ 9153533Sheideman { &vop_close_desc, ufsspec_close }, /* close */ 9253533Sheideman { &vop_access_desc, ufs_access }, /* access */ 9353533Sheideman { &vop_getattr_desc, ufs_getattr }, /* getattr */ 9453533Sheideman { &vop_setattr_desc, ufs_setattr }, /* setattr */ 9553533Sheideman { &vop_read_desc, ufsspec_read }, /* read */ 9653533Sheideman { &vop_write_desc, ufsspec_write }, /* write */ 9753533Sheideman { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ 9853533Sheideman { &vop_select_desc, spec_select }, /* select */ 9954030Smckusick { &vop_mmap_desc, spec_mmap }, /* mmap */ 10053533Sheideman { &vop_fsync_desc, spec_fsync }, /* fsync */ 10154030Smckusick { &vop_seek_desc, spec_seek }, /* seek */ 10253533Sheideman { &vop_remove_desc, spec_remove }, /* remove */ 10354030Smckusick { &vop_link_desc, spec_link }, /* link */ 10453533Sheideman { &vop_rename_desc, spec_rename }, /* rename */ 10553533Sheideman { &vop_mkdir_desc, spec_mkdir }, /* mkdir */ 10653533Sheideman { &vop_rmdir_desc, spec_rmdir }, /* rmdir */ 10753533Sheideman { &vop_symlink_desc, spec_symlink }, /* symlink */ 10853533Sheideman { &vop_readdir_desc, spec_readdir }, /* readdir */ 10953533Sheideman { &vop_readlink_desc, spec_readlink }, /* readlink */ 11053533Sheideman { &vop_abortop_desc, spec_abortop }, /* abortop */ 11153533Sheideman { &vop_inactive_desc, lfs_inactive }, /* inactive */ 11253533Sheideman { &vop_reclaim_desc, ufs_reclaim }, /* reclaim */ 11354030Smckusick { &vop_lock_desc, ufs_lock }, /* lock */ 11453533Sheideman { &vop_unlock_desc, ufs_unlock }, /* unlock */ 11554030Smckusick { &vop_bmap_desc, spec_bmap }, /* bmap */ 11653533Sheideman { &vop_strategy_desc, spec_strategy }, /* strategy */ 11754030Smckusick { &vop_print_desc, ufs_print }, /* print */ 11853533Sheideman { &vop_islocked_desc, ufs_islocked }, /* islocked */ 11953533Sheideman { &vop_advlock_desc, spec_advlock }, /* advlock */ 12053533Sheideman { &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */ 12153533Sheideman { &vop_valloc_desc, spec_valloc }, /* valloc */ 12254030Smckusick { &vop_vfree_desc, lfs_vfree }, /* vfree */ 12353533Sheideman { &vop_truncate_desc, spec_truncate }, /* truncate */ 12453533Sheideman { &vop_update_desc, lfs_update }, /* update */ 12553533Sheideman { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */ 12653533Sheideman { (struct vnodeop_desc*)NULL, (int(*)())NULL } 12751558Smckusick }; 12853533Sheideman struct vnodeopv_desc lfs_specop_opv_desc = 12953533Sheideman { &lfs_specop_p, lfs_specop_entries }; 13051558Smckusick 13151558Smckusick #ifdef FIFO 13253533Sheideman int (**lfs_fifoop_p)(); 13353533Sheideman struct vnodeopv_entry_desc lfs_fifoop_entries[] = { 13453533Sheideman { &vop_default_desc, vn_default_error }, 13553533Sheideman { &vop_lookup_desc, fifo_lookup }, /* lookup */ 13653533Sheideman { &vop_create_desc, fifo_create }, /* create */ 13753533Sheideman { &vop_mknod_desc, fifo_mknod }, /* mknod */ 13854030Smckusick { &vop_open_desc, fifo_open }, /* open */ 13953533Sheideman { &vop_close_desc, ufsfifo_close }, /* close */ 14053533Sheideman { &vop_access_desc, ufs_access }, /* access */ 14153533Sheideman { &vop_getattr_desc, ufs_getattr }, /* getattr */ 14253533Sheideman { &vop_setattr_desc, ufs_setattr }, /* setattr */ 14353533Sheideman { &vop_read_desc, ufsfifo_read }, /* read */ 14453533Sheideman { &vop_write_desc, ufsfifo_write }, /* write */ 14553533Sheideman { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ 14653533Sheideman { &vop_select_desc, fifo_select }, /* select */ 14754030Smckusick { &vop_mmap_desc, fifo_mmap }, /* mmap */ 14853533Sheideman { &vop_fsync_desc, fifo_fsync }, /* fsync */ 14954030Smckusick { &vop_seek_desc, fifo_seek }, /* seek */ 15053533Sheideman { &vop_remove_desc, fifo_remove }, /* remove */ 15154030Smckusick { &vop_link_desc, fifo_link }, /* link */ 15253533Sheideman { &vop_rename_desc, fifo_rename }, /* rename */ 15353533Sheideman { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ 15453533Sheideman { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ 15553533Sheideman { &vop_symlink_desc, fifo_symlink }, /* symlink */ 15653533Sheideman { &vop_readdir_desc, fifo_readdir }, /* readdir */ 15753533Sheideman { &vop_readlink_desc, fifo_readlink }, /* readlink */ 15853533Sheideman { &vop_abortop_desc, fifo_abortop }, /* abortop */ 15953533Sheideman { &vop_inactive_desc, lfs_inactive }, /* inactive */ 16053533Sheideman { &vop_reclaim_desc, ufs_reclaim }, /* reclaim */ 16154030Smckusick { &vop_lock_desc, ufs_lock }, /* lock */ 16253533Sheideman { &vop_unlock_desc, ufs_unlock }, /* unlock */ 16354030Smckusick { &vop_bmap_desc, fifo_bmap }, /* bmap */ 16453533Sheideman { &vop_strategy_desc, fifo_strategy }, /* strategy */ 16554030Smckusick { &vop_print_desc, ufs_print }, /* print */ 16653533Sheideman { &vop_islocked_desc, ufs_islocked }, /* islocked */ 16753533Sheideman { &vop_advlock_desc, fifo_advlock }, /* advlock */ 16853533Sheideman { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */ 16953533Sheideman { &vop_valloc_desc, fifo_valloc }, /* valloc */ 17054030Smckusick { &vop_vfree_desc, lfs_vfree }, /* vfree */ 17153533Sheideman { &vop_truncate_desc, fifo_truncate }, /* truncate */ 17253533Sheideman { &vop_update_desc, lfs_update }, /* update */ 17353533Sheideman { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */ 17453533Sheideman { (struct vnodeop_desc*)NULL, (int(*)())NULL } 17551558Smckusick }; 17653533Sheideman struct vnodeopv_desc lfs_fifoop_opv_desc = 17753533Sheideman { &lfs_fifoop_p, lfs_fifoop_entries }; 17851558Smckusick #endif /* FIFO */ 17951558Smckusick 18037Sbill /* 18139608Smckusick * Vnode op for reading. 18239608Smckusick */ 18337737Smckusick /* ARGSUSED */ 18454030Smckusick lfs_read(ap) 18554692Sbostic struct vop_read_args /* { 18654692Sbostic struct vnode *a_vp; 18754692Sbostic struct uio *a_uio; 18854692Sbostic int a_ioflag; 18954692Sbostic struct ucred *a_cred; 19054692Sbostic } */ *ap; 19139608Smckusick { 19253867Sheideman register struct uio *uio = ap->a_uio; 19353593Sheideman register struct inode *ip = VTOI(ap->a_vp); 19451502Sbostic register struct lfs *fs; /* LFS */ 19539608Smckusick struct buf *bp; 19639608Smckusick daddr_t lbn, bn, rablock; 19753233Smckusick int size, error = 0; 19839608Smckusick long n, on, type; 19953233Smckusick off_t diff; 20039608Smckusick 20151852Sbostic #ifdef VERBOSE 20251852Sbostic printf("lfs_read: ino %d\n", ip->i_number); 20351852Sbostic #endif 20448039Smckusick #ifdef DIAGNOSTIC 20553867Sheideman if (uio->uio_rw != UIO_READ) 20639608Smckusick panic("ufs_read mode"); 20739608Smckusick type = ip->i_mode & IFMT; 20839608Smckusick if (type != IFDIR && type != IFREG && type != IFLNK) 20939608Smckusick panic("ufs_read type"); 21048039Smckusick #endif 21153867Sheideman if (uio->uio_resid == 0) 21239608Smckusick return (0); 21353867Sheideman if (uio->uio_offset < 0) 21439608Smckusick return (EINVAL); 21539608Smckusick ip->i_flag |= IACC; 21651155Sbostic 21751155Sbostic fs = ip->i_lfs; /* LFS */ 21839608Smckusick do { 21953867Sheideman lbn = lblkno(fs, uio->uio_offset); 22053867Sheideman on = blkoff(fs, uio->uio_offset); 22153867Sheideman n = MIN((unsigned)(fs->lfs_bsize - on), uio->uio_resid); 22253867Sheideman diff = ip->i_size - uio->uio_offset; 22339608Smckusick if (diff <= 0) 22439608Smckusick return (0); 22539608Smckusick if (diff < n) 22639608Smckusick n = diff; 22751155Sbostic size = blksize(fs); /* LFS */ 22839674Smckusick rablock = lbn + 1; 22953593Sheideman if (ap->a_vp->v_lastr + 1 == lbn && 23039896Smckusick lblktosize(fs, rablock) < ip->i_size) 23152195Smckusick error = breadn(ITOV(ip), lbn, size, &rablock, 23252195Smckusick &size, 1, NOCRED, &bp); 23339608Smckusick else 23439674Smckusick error = bread(ITOV(ip), lbn, size, NOCRED, &bp); 23553593Sheideman ap->a_vp->v_lastr = lbn; 23639608Smckusick n = MIN(n, size - bp->b_resid); 23739608Smckusick if (error) { 23839608Smckusick brelse(bp); 23939608Smckusick return (error); 24039608Smckusick } 24153867Sheideman error = uiomove(bp->b_un.b_addr + on, (int)n, uio); 24253867Sheideman if (n + on == fs->lfs_bsize || uio->uio_offset == ip->i_size) 24339608Smckusick bp->b_flags |= B_AGE; 24439608Smckusick brelse(bp); 24553867Sheideman } while (error == 0 && uio->uio_resid > 0 && n != 0); 24639608Smckusick return (error); 24739608Smckusick } 24839608Smckusick 24939608Smckusick /* 25039608Smckusick * Vnode op for writing. 25139608Smckusick */ 25254030Smckusick lfs_write(ap) 25354692Sbostic struct vop_write_args /* { 25454692Sbostic struct vnode *a_vp; 25554692Sbostic struct uio *a_uio; 25654692Sbostic int a_ioflag; 25754692Sbostic struct ucred *a_cred; 25854692Sbostic } */ *ap; 25939608Smckusick { 26053867Sheideman register struct vnode *vp = ap->a_vp; 26154030Smckusick register struct uio *uio = ap->a_uio; 26254030Smckusick struct proc *p = uio->uio_procp; 26353867Sheideman register struct inode *ip = VTOI(vp); 26452091Sbostic register struct lfs *fs; 26554030Smckusick register ioflag = ap->a_ioflag; 266*54765Smckusick struct timeval tv; 26739608Smckusick struct buf *bp; 26852091Sbostic daddr_t lbn; 26953233Smckusick off_t osize; 27052091Sbostic int n, on, flags, newblock; 27145722Smckusick int size, resid, error = 0; 27239608Smckusick 27351852Sbostic #ifdef VERBOSE 27451852Sbostic printf("lfs_write ino %d\n", ip->i_number); 27551852Sbostic #endif 27648039Smckusick #ifdef DIAGNOSTIC 27754030Smckusick if (uio->uio_rw != UIO_WRITE) 27852091Sbostic panic("lfs_write mode"); 27948039Smckusick #endif 28053867Sheideman switch (vp->v_type) { 28139608Smckusick case VREG: 28254030Smckusick if (ioflag & IO_APPEND) 28354030Smckusick uio->uio_offset = ip->i_size; 28439608Smckusick /* fall through */ 28539608Smckusick case VLNK: 28639608Smckusick break; 28739608Smckusick 28839608Smckusick case VDIR: 28952091Sbostic /* XXX This may not be correct for LFS. */ 29054030Smckusick if ((ioflag & IO_SYNC) == 0) 29152091Sbostic panic("lfs_write nonsync dir write"); 29239608Smckusick break; 29339608Smckusick 29439608Smckusick default: 29552091Sbostic panic("lfs_write type"); 29639608Smckusick } 29754030Smckusick if (uio->uio_offset < 0) 29839608Smckusick return (EINVAL); 29954030Smckusick if (uio->uio_resid == 0) 30039608Smckusick return (0); 30139608Smckusick /* 30239608Smckusick * Maybe this should be above the vnode op call, but so long as 30339608Smckusick * file servers have no limits, i don't think it matters 30439608Smckusick */ 30553867Sheideman if (vp->v_type == VREG && p && 30654030Smckusick uio->uio_offset + uio->uio_resid > 30747571Skarels p->p_rlimit[RLIMIT_FSIZE].rlim_cur) { 30847571Skarels psignal(p, SIGXFSZ); 30939608Smckusick return (EFBIG); 31039608Smckusick } 31154030Smckusick resid = uio->uio_resid; 31239608Smckusick osize = ip->i_size; 31351183Sbostic fs = ip->i_lfs; /* LFS */ 31439674Smckusick flags = 0; 31551183Sbostic #ifdef NOTLFS 31654030Smckusick if (ioflag & IO_SYNC) 31739674Smckusick flags = B_SYNC; 31851183Sbostic #endif 31939608Smckusick do { 32054030Smckusick lbn = lblkno(fs, uio->uio_offset); 32154030Smckusick on = blkoff(fs, uio->uio_offset); 32254030Smckusick n = MIN((unsigned)(fs->lfs_bsize - on), uio->uio_resid); 32353867Sheideman if (error = lfs_balloc(vp, n, lbn, &bp)) 32439608Smckusick break; 32554030Smckusick if (uio->uio_offset + n > ip->i_size) { 32654030Smckusick ip->i_size = uio->uio_offset + n; 32753867Sheideman vnode_pager_setsize(vp, (u_long)ip->i_size); 32845722Smckusick } 32951183Sbostic size = blksize(fs); 33053867Sheideman (void) vnode_pager_uncache(vp); 33139608Smckusick n = MIN(n, size - bp->b_resid); 33254030Smckusick error = uiomove(bp->b_un.b_addr + on, n, uio); 33351183Sbostic #ifdef NOTLFS /* LFS */ 33454030Smckusick if (ioflag & IO_SYNC) 33539608Smckusick (void) bwrite(bp); 33639608Smckusick else if (n + on == fs->fs_bsize) { 33739608Smckusick bp->b_flags |= B_AGE; 33839608Smckusick bawrite(bp); 33939608Smckusick } else 34039608Smckusick bdwrite(bp); 34152091Sbostic ip->i_flag |= IUPD|ICHG; 34251183Sbostic #else 34352091Sbostic /* XXX This doesn't handle IO_SYNC. */ 34452091Sbostic LFS_UBWRITE(bp); 34551183Sbostic #endif 34653593Sheideman if (ap->a_cred->cr_uid != 0) 34739608Smckusick ip->i_mode &= ~(ISUID|ISGID); 34854030Smckusick } while (error == 0 && uio->uio_resid > 0 && n != 0); 34954030Smckusick if (error && (ioflag & IO_UNIT)) { 35054692Sbostic (void)VOP_TRUNCATE(vp, osize, ioflag & IO_SYNC, ap->a_cred, 35154692Sbostic uio->uio_procp); 35254030Smckusick uio->uio_offset -= resid - uio->uio_resid; 35354030Smckusick uio->uio_resid = resid; 35439608Smckusick } 355*54765Smckusick if (!error && (ioflag & IO_SYNC)) { 356*54765Smckusick tv = time; 357*54765Smckusick error = VOP_UPDATE(vp, &tv, &tv, 1); 358*54765Smckusick } 35939608Smckusick return (error); 36039608Smckusick } 36139608Smckusick 3629167Ssam /* 36337737Smckusick * Synch an open file. 3649167Ssam */ 36537737Smckusick /* ARGSUSED */ 36654030Smckusick lfs_fsync(ap) 36754692Sbostic struct vop_fsync_args /* { 36854692Sbostic struct vnode *a_vp; 36954692Sbostic struct ucred *a_cred; 37054692Sbostic int a_waitfor; 37154692Sbostic struct proc *a_p; 37254692Sbostic } */ *ap; 3737701Ssam { 374*54765Smckusick struct timeval tv; 3757701Ssam 37651852Sbostic #ifdef VERBOSE 37751852Sbostic printf("lfs_fsync\n"); 37851852Sbostic #endif 379*54765Smckusick tv = time; 380*54765Smckusick return (VOP_UPDATE(ap->a_vp, &tv, &tv, ap->a_waitfor == MNT_WAIT)); 38137737Smckusick } 38251558Smckusick 38351558Smckusick /* 38451558Smckusick * Last reference to an inode, write the inode out and if necessary, 38551558Smckusick * truncate and deallocate the file. 38651558Smckusick */ 38751558Smckusick int 38854030Smckusick lfs_inactive(ap) 38954692Sbostic struct vop_inactive_args /* { 39054692Sbostic struct vnode *a_vp; 39154692Sbostic } */ *ap; 39251558Smckusick { 39351852Sbostic extern int prtactive; 39454030Smckusick register struct vnode *vp = ap->a_vp; 39551558Smckusick register struct inode *ip; 396*54765Smckusick struct timeval tv; 39751558Smckusick int mode, error; 39851558Smckusick 39951852Sbostic #ifdef VERBOSE 40051852Sbostic printf("lfs_inactive\n"); 40151852Sbostic #endif 40254030Smckusick if (prtactive && vp->v_usecount != 0) 40354030Smckusick vprint("lfs_inactive: pushing active", vp); 40451558Smckusick 40551558Smckusick /* Get rid of inodes related to stale file handles. */ 40654030Smckusick ip = VTOI(vp); 40751558Smckusick if (ip->i_mode == 0) { 40854030Smckusick if ((vp->v_flag & VXLOCK) == 0) 40954030Smckusick vgone(vp); 41051558Smckusick return (0); 41151558Smckusick } 41251558Smckusick 41351558Smckusick error = 0; 41451558Smckusick ILOCK(ip); 41554030Smckusick if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 41651558Smckusick #ifdef QUOTA 41751558Smckusick if (!getinoquota(ip)) 41851558Smckusick (void)chkiq(ip, -1, NOCRED, 0); 41951558Smckusick #endif 42054692Sbostic error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, NULL); 42151558Smckusick mode = ip->i_mode; 42251558Smckusick ip->i_mode = 0; 42351558Smckusick ip->i_rdev = 0; 42451558Smckusick ip->i_flag |= IUPD|ICHG; 42554030Smckusick VOP_VFREE(vp, ip->i_number, mode); 42651558Smckusick } 427*54765Smckusick if (ip->i_flag&(IUPD|IACC|ICHG|IMOD)) { 428*54765Smckusick tv = time; 429*54765Smckusick VOP_UPDATE(vp, &tv, &tv, 0); 430*54765Smckusick } 43151558Smckusick IUNLOCK(ip); 43251558Smckusick ip->i_flag = 0; 43351558Smckusick /* 43451558Smckusick * If we are done with the inode, reclaim it 43551558Smckusick * so that it can be reused immediately. 43651558Smckusick */ 43754030Smckusick if (vp->v_usecount == 0 && ip->i_mode == 0) 43854030Smckusick vgone(vp); 43951558Smckusick return (error); 44051558Smckusick } 44154264Sbostic 44254264Sbostic /* 44354264Sbostic * These macros are used to bracket UFS directory ops, so that we can 44454264Sbostic * identify all the pages touched during directory ops which need to 44554264Sbostic * be ordered and flushed atomically, so that they may be recovered. 44654264Sbostic */ 44754264Sbostic #define SET_DIROP(fs) { \ 44854264Sbostic int __s; \ 44954264Sbostic __s = splbio(); \ 45054264Sbostic if ((fs)->lfs_writer) \ 45154264Sbostic tsleep(&(fs)->lfs_dirops, PRIBIO + 1, "lfs dirop", 0); \ 45254264Sbostic ++(fs)->lfs_dirops; \ 45354264Sbostic (fs)->lfs_doifile = 1; \ 45454264Sbostic splx(__s); \ 45554264Sbostic } 45654264Sbostic 45754264Sbostic #define SET_ENDOP(fs) { \ 45854264Sbostic int __s; \ 45954264Sbostic __s = splbio(); \ 46054264Sbostic --(fs)->lfs_dirops; \ 46154264Sbostic if (!(fs)->lfs_dirops) \ 46254264Sbostic wakeup(&(fs)->lfs_writer); \ 46354264Sbostic splx(__s); \ 46454264Sbostic } 46554264Sbostic 46654264Sbostic #define MARK_VNODE(dvp) (dvp)->v_flag |= VDIROP 46754264Sbostic 46854264Sbostic int 46954264Sbostic lfs_symlink(ap) 47054692Sbostic struct vop_symlink_args /* { 47154692Sbostic struct vnode *a_dvp; 47254692Sbostic struct vnode **a_vpp; 47354692Sbostic struct componentname *a_cnp; 47454692Sbostic struct vattr *a_vap; 47554692Sbostic char *a_target; 47654692Sbostic } */ *ap; 47754264Sbostic { 47854264Sbostic int ret; 47954264Sbostic 48054264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 48154264Sbostic MARK_VNODE(ap->a_dvp); 48254264Sbostic ret = ufs_symlink(ap); 48354264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 48454264Sbostic return (ret); 48554264Sbostic } 48654264Sbostic 48754264Sbostic int 48854264Sbostic lfs_mknod(ap) 48954692Sbostic struct vop_mknod_args /* { 49054692Sbostic struct vnode *a_dvp; 49154692Sbostic struct vnode **a_vpp; 49254692Sbostic struct componentname *a_cnp; 49354692Sbostic struct vattr *a_vap; 49454692Sbostic } */ *ap; 49554264Sbostic { 49654264Sbostic int ret; 49754264Sbostic 49854264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 49954264Sbostic MARK_VNODE(ap->a_dvp); 50054264Sbostic ret = ufs_mknod(ap); 50154264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 50254264Sbostic return (ret); 50354264Sbostic } 50454264Sbostic 50554264Sbostic int 50654264Sbostic lfs_create(ap) 50754692Sbostic struct vop_create_args /* { 50854692Sbostic struct vnode *a_dvp; 50954692Sbostic struct vnode **a_vpp; 51054692Sbostic struct componentname *a_cnp; 51154692Sbostic struct vattr *a_vap; 51254692Sbostic } */ *ap; 51354264Sbostic { 51454264Sbostic int ret; 51554264Sbostic 51654264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 51754264Sbostic MARK_VNODE(ap->a_dvp); 51854264Sbostic ret = ufs_create(ap); 51954264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 52054264Sbostic return (ret); 52154264Sbostic } 52254264Sbostic 52354264Sbostic int 52454264Sbostic lfs_mkdir(ap) 52554692Sbostic struct vop_mkdir_args /* { 52654692Sbostic struct vnode *a_dvp; 52754692Sbostic struct vnode **a_vpp; 52854692Sbostic struct componentname *a_cnp; 52954692Sbostic struct vattr *a_vap; 53054692Sbostic } */ *ap; 53154264Sbostic { 53254264Sbostic int ret; 53354264Sbostic 53454264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 53554264Sbostic MARK_VNODE(ap->a_dvp); 53654264Sbostic ret = ufs_mkdir(ap); 53754264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 53854264Sbostic return (ret); 53954264Sbostic } 54054264Sbostic 54154264Sbostic int 54254264Sbostic lfs_remove(ap) 54354692Sbostic struct vop_remove_args /* { 54454692Sbostic struct vnode *a_dvp; 54554692Sbostic struct vnode *a_vp; 54654692Sbostic struct componentname *a_cnp; 54754692Sbostic } */ *ap; 54854264Sbostic { 54954264Sbostic int ret; 55054264Sbostic 55154264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 55254264Sbostic MARK_VNODE(ap->a_dvp); 55354264Sbostic MARK_VNODE(ap->a_vp); 55454264Sbostic ret = ufs_remove(ap); 55554264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 55654264Sbostic return (ret); 55754264Sbostic } 55854264Sbostic 55954264Sbostic int 56054264Sbostic lfs_rmdir(ap) 56154692Sbostic struct vop_rmdir_args /* { 56254692Sbostic struct vnodeop_desc *a_desc; 56354692Sbostic struct vnode *a_dvp; 56454692Sbostic struct vnode *a_vp; 56554692Sbostic struct componentname *a_cnp; 56654692Sbostic } */ *ap; 56754264Sbostic { 56854264Sbostic int ret; 56954264Sbostic 57054264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 57154264Sbostic MARK_VNODE(ap->a_dvp); 57254264Sbostic MARK_VNODE(ap->a_vp); 57354264Sbostic ret = ufs_rmdir(ap); 57454264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 57554264Sbostic return (ret); 57654264Sbostic } 57754264Sbostic 57854264Sbostic int 57954264Sbostic lfs_link(ap) 58054692Sbostic struct vop_link_args /* { 58154692Sbostic struct vnode *a_vp; 58254692Sbostic struct vnode *a_tdvp; 58354692Sbostic struct componentname *a_cnp; 58454692Sbostic } */ *ap; 58554264Sbostic { 58654264Sbostic int ret; 58754264Sbostic 58854264Sbostic SET_DIROP(VTOI(ap->a_vp)->i_lfs); 58954264Sbostic MARK_VNODE(ap->a_vp); 59054264Sbostic ret = ufs_link(ap); 59154264Sbostic SET_ENDOP(VTOI(ap->a_vp)->i_lfs); 59254264Sbostic return (ret); 59354264Sbostic } 59454264Sbostic 59554264Sbostic int 59654264Sbostic lfs_rename(ap) 59754692Sbostic struct vop_rename_args /* { 59854692Sbostic struct vnode *a_fdvp; 59954692Sbostic struct vnode *a_fvp; 60054692Sbostic struct componentname *a_fcnp; 60154692Sbostic struct vnode *a_tdvp; 60254692Sbostic struct vnode *a_tvp; 60354692Sbostic struct componentname *a_tcnp; 60454692Sbostic } */ *ap; 60554264Sbostic { 60654264Sbostic int ret; 60754264Sbostic 60854264Sbostic SET_DIROP(VTOI(ap->a_fdvp)->i_lfs); 60954264Sbostic MARK_VNODE(ap->a_fdvp); 61054264Sbostic MARK_VNODE(ap->a_tdvp); 61154264Sbostic ret = ufs_rename(ap); 61254264Sbostic SET_ENDOP(VTOI(ap->a_fdvp)->i_lfs); 61354264Sbostic return (ret); 61454264Sbostic } 615