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*55936Sbostic * @(#)lfs_vnops.c 7.91 (Berkeley) 08/21/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> 32*55936Sbostic #include <ufs/ufs/ufsmount.h> 3351502Sbostic #include <ufs/ufs/ufs_extern.h> 3447571Skarels 3551502Sbostic #include <ufs/lfs/lfs.h> 3651502Sbostic #include <ufs/lfs/lfs_extern.h> 3751134Sbostic 3851482Sbostic /* Global vfs data structures for lfs. */ 3953533Sheideman int (**lfs_vnodeop_p)(); 4053533Sheideman struct vnodeopv_entry_desc lfs_vnodeop_entries[] = { 4153533Sheideman { &vop_default_desc, vn_default_error }, 4253533Sheideman { &vop_lookup_desc, ufs_lookup }, /* lookup */ 4354264Sbostic { &vop_create_desc, lfs_create }, /* create */ 4454264Sbostic { &vop_mknod_desc, lfs_mknod }, /* mknod */ 4554030Smckusick { &vop_open_desc, ufs_open }, /* open */ 4654030Smckusick { &vop_close_desc, ufs_close }, /* close */ 4753533Sheideman { &vop_access_desc, ufs_access }, /* access */ 48*55936Sbostic { &vop_getattr_desc, lfs_getattr }, /* getattr */ 4953533Sheideman { &vop_setattr_desc, ufs_setattr }, /* setattr */ 5054030Smckusick { &vop_read_desc, lfs_read }, /* read */ 5154030Smckusick { &vop_write_desc, lfs_write }, /* write */ 5254030Smckusick { &vop_ioctl_desc, ufs_ioctl }, /* ioctl */ 5353533Sheideman { &vop_select_desc, ufs_select }, /* select */ 5454030Smckusick { &vop_mmap_desc, ufs_mmap }, /* mmap */ 5554030Smckusick { &vop_fsync_desc, lfs_fsync }, /* fsync */ 5654030Smckusick { &vop_seek_desc, ufs_seek }, /* seek */ 5754264Sbostic { &vop_remove_desc, lfs_remove }, /* remove */ 5854264Sbostic { &vop_link_desc, lfs_link }, /* link */ 5954264Sbostic { &vop_rename_desc, lfs_rename }, /* rename */ 6054264Sbostic { &vop_mkdir_desc, lfs_mkdir }, /* mkdir */ 6154264Sbostic { &vop_rmdir_desc, lfs_rmdir }, /* rmdir */ 6254264Sbostic { &vop_symlink_desc, lfs_symlink }, /* symlink */ 6353533Sheideman { &vop_readdir_desc, ufs_readdir }, /* readdir */ 6453533Sheideman { &vop_readlink_desc, ufs_readlink }, /* readlink */ 6553533Sheideman { &vop_abortop_desc, ufs_abortop }, /* abortop */ 6653533Sheideman { &vop_inactive_desc, lfs_inactive }, /* inactive */ 6753533Sheideman { &vop_reclaim_desc, ufs_reclaim }, /* reclaim */ 6854030Smckusick { &vop_lock_desc, ufs_lock }, /* lock */ 6953533Sheideman { &vop_unlock_desc, ufs_unlock }, /* unlock */ 7054030Smckusick { &vop_bmap_desc, lfs_bmap }, /* bmap */ 7153533Sheideman { &vop_strategy_desc, ufs_strategy }, /* strategy */ 7254030Smckusick { &vop_print_desc, ufs_print }, /* print */ 7353533Sheideman { &vop_islocked_desc, ufs_islocked }, /* islocked */ 7453533Sheideman { &vop_advlock_desc, ufs_advlock }, /* advlock */ 7553533Sheideman { &vop_blkatoff_desc, lfs_blkatoff }, /* blkatoff */ 7653533Sheideman { &vop_valloc_desc, lfs_valloc }, /* valloc */ 7754030Smckusick { &vop_vfree_desc, lfs_vfree }, /* vfree */ 7853533Sheideman { &vop_truncate_desc, lfs_truncate }, /* truncate */ 7953533Sheideman { &vop_update_desc, lfs_update }, /* update */ 8053533Sheideman { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */ 8153533Sheideman { (struct vnodeop_desc*)NULL, (int(*)())NULL } 8251482Sbostic }; 8353533Sheideman struct vnodeopv_desc lfs_vnodeop_opv_desc = 8453533Sheideman { &lfs_vnodeop_p, lfs_vnodeop_entries }; 856254Sroot 8653533Sheideman int (**lfs_specop_p)(); 8753533Sheideman struct vnodeopv_entry_desc lfs_specop_entries[] = { 8853533Sheideman { &vop_default_desc, vn_default_error }, 8953533Sheideman { &vop_lookup_desc, spec_lookup }, /* lookup */ 9053533Sheideman { &vop_create_desc, spec_create }, /* create */ 9153533Sheideman { &vop_mknod_desc, spec_mknod }, /* mknod */ 9254030Smckusick { &vop_open_desc, spec_open }, /* open */ 9353533Sheideman { &vop_close_desc, ufsspec_close }, /* close */ 9453533Sheideman { &vop_access_desc, ufs_access }, /* access */ 95*55936Sbostic { &vop_getattr_desc, lfs_getattr }, /* getattr */ 9653533Sheideman { &vop_setattr_desc, ufs_setattr }, /* setattr */ 9753533Sheideman { &vop_read_desc, ufsspec_read }, /* read */ 9853533Sheideman { &vop_write_desc, ufsspec_write }, /* write */ 9953533Sheideman { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ 10053533Sheideman { &vop_select_desc, spec_select }, /* select */ 10154030Smckusick { &vop_mmap_desc, spec_mmap }, /* mmap */ 10253533Sheideman { &vop_fsync_desc, spec_fsync }, /* fsync */ 10354030Smckusick { &vop_seek_desc, spec_seek }, /* seek */ 10453533Sheideman { &vop_remove_desc, spec_remove }, /* remove */ 10554030Smckusick { &vop_link_desc, spec_link }, /* link */ 10653533Sheideman { &vop_rename_desc, spec_rename }, /* rename */ 10753533Sheideman { &vop_mkdir_desc, spec_mkdir }, /* mkdir */ 10853533Sheideman { &vop_rmdir_desc, spec_rmdir }, /* rmdir */ 10953533Sheideman { &vop_symlink_desc, spec_symlink }, /* symlink */ 11053533Sheideman { &vop_readdir_desc, spec_readdir }, /* readdir */ 11153533Sheideman { &vop_readlink_desc, spec_readlink }, /* readlink */ 11253533Sheideman { &vop_abortop_desc, spec_abortop }, /* abortop */ 11353533Sheideman { &vop_inactive_desc, lfs_inactive }, /* inactive */ 11453533Sheideman { &vop_reclaim_desc, ufs_reclaim }, /* reclaim */ 11554030Smckusick { &vop_lock_desc, ufs_lock }, /* lock */ 11653533Sheideman { &vop_unlock_desc, ufs_unlock }, /* unlock */ 11754030Smckusick { &vop_bmap_desc, spec_bmap }, /* bmap */ 11853533Sheideman { &vop_strategy_desc, spec_strategy }, /* strategy */ 11954030Smckusick { &vop_print_desc, ufs_print }, /* print */ 12053533Sheideman { &vop_islocked_desc, ufs_islocked }, /* islocked */ 12153533Sheideman { &vop_advlock_desc, spec_advlock }, /* advlock */ 12253533Sheideman { &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */ 12353533Sheideman { &vop_valloc_desc, spec_valloc }, /* valloc */ 12454030Smckusick { &vop_vfree_desc, lfs_vfree }, /* vfree */ 12553533Sheideman { &vop_truncate_desc, spec_truncate }, /* truncate */ 12653533Sheideman { &vop_update_desc, lfs_update }, /* update */ 12753533Sheideman { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */ 12853533Sheideman { (struct vnodeop_desc*)NULL, (int(*)())NULL } 12951558Smckusick }; 13053533Sheideman struct vnodeopv_desc lfs_specop_opv_desc = 13153533Sheideman { &lfs_specop_p, lfs_specop_entries }; 13251558Smckusick 13351558Smckusick #ifdef FIFO 13453533Sheideman int (**lfs_fifoop_p)(); 13553533Sheideman struct vnodeopv_entry_desc lfs_fifoop_entries[] = { 13653533Sheideman { &vop_default_desc, vn_default_error }, 13753533Sheideman { &vop_lookup_desc, fifo_lookup }, /* lookup */ 13853533Sheideman { &vop_create_desc, fifo_create }, /* create */ 13953533Sheideman { &vop_mknod_desc, fifo_mknod }, /* mknod */ 14054030Smckusick { &vop_open_desc, fifo_open }, /* open */ 14153533Sheideman { &vop_close_desc, ufsfifo_close }, /* close */ 14253533Sheideman { &vop_access_desc, ufs_access }, /* access */ 143*55936Sbostic { &vop_getattr_desc, lfs_getattr }, /* getattr */ 14453533Sheideman { &vop_setattr_desc, ufs_setattr }, /* setattr */ 14553533Sheideman { &vop_read_desc, ufsfifo_read }, /* read */ 14653533Sheideman { &vop_write_desc, ufsfifo_write }, /* write */ 14753533Sheideman { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ 14853533Sheideman { &vop_select_desc, fifo_select }, /* select */ 14954030Smckusick { &vop_mmap_desc, fifo_mmap }, /* mmap */ 15053533Sheideman { &vop_fsync_desc, fifo_fsync }, /* fsync */ 15154030Smckusick { &vop_seek_desc, fifo_seek }, /* seek */ 15253533Sheideman { &vop_remove_desc, fifo_remove }, /* remove */ 15354030Smckusick { &vop_link_desc, fifo_link }, /* link */ 15453533Sheideman { &vop_rename_desc, fifo_rename }, /* rename */ 15553533Sheideman { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ 15653533Sheideman { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ 15753533Sheideman { &vop_symlink_desc, fifo_symlink }, /* symlink */ 15853533Sheideman { &vop_readdir_desc, fifo_readdir }, /* readdir */ 15953533Sheideman { &vop_readlink_desc, fifo_readlink }, /* readlink */ 16053533Sheideman { &vop_abortop_desc, fifo_abortop }, /* abortop */ 16153533Sheideman { &vop_inactive_desc, lfs_inactive }, /* inactive */ 16253533Sheideman { &vop_reclaim_desc, ufs_reclaim }, /* reclaim */ 16354030Smckusick { &vop_lock_desc, ufs_lock }, /* lock */ 16453533Sheideman { &vop_unlock_desc, ufs_unlock }, /* unlock */ 16554030Smckusick { &vop_bmap_desc, fifo_bmap }, /* bmap */ 16653533Sheideman { &vop_strategy_desc, fifo_strategy }, /* strategy */ 16754030Smckusick { &vop_print_desc, ufs_print }, /* print */ 16853533Sheideman { &vop_islocked_desc, ufs_islocked }, /* islocked */ 16953533Sheideman { &vop_advlock_desc, fifo_advlock }, /* advlock */ 17053533Sheideman { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */ 17153533Sheideman { &vop_valloc_desc, fifo_valloc }, /* valloc */ 17254030Smckusick { &vop_vfree_desc, lfs_vfree }, /* vfree */ 17353533Sheideman { &vop_truncate_desc, fifo_truncate }, /* truncate */ 17453533Sheideman { &vop_update_desc, lfs_update }, /* update */ 17553533Sheideman { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */ 17653533Sheideman { (struct vnodeop_desc*)NULL, (int(*)())NULL } 17751558Smckusick }; 17853533Sheideman struct vnodeopv_desc lfs_fifoop_opv_desc = 17953533Sheideman { &lfs_fifoop_p, lfs_fifoop_entries }; 18051558Smckusick #endif /* FIFO */ 18151558Smckusick 18237Sbill /* 18339608Smckusick * Vnode op for reading. 18439608Smckusick */ 18537737Smckusick /* ARGSUSED */ 18654030Smckusick lfs_read(ap) 18754692Sbostic struct vop_read_args /* { 18854692Sbostic struct vnode *a_vp; 18954692Sbostic struct uio *a_uio; 19054692Sbostic int a_ioflag; 19154692Sbostic struct ucred *a_cred; 19254692Sbostic } */ *ap; 19339608Smckusick { 19455460Sbostic register struct vnode *vp = ap->a_vp; 19555460Sbostic register struct inode *ip = VTOI(vp); 19653867Sheideman register struct uio *uio = ap->a_uio; 19755460Sbostic register struct lfs *fs; 19839608Smckusick struct buf *bp; 19939608Smckusick daddr_t lbn, bn, rablock; 20053233Smckusick off_t diff; 20155460Sbostic int error = 0, size; 20255460Sbostic long n, on; 20339608Smckusick 20448039Smckusick #ifdef DIAGNOSTIC 20555460Sbostic int type; 20653867Sheideman if (uio->uio_rw != UIO_READ) 20755460Sbostic panic("lfs_read mode"); 20839608Smckusick type = ip->i_mode & IFMT; 20939608Smckusick if (type != IFDIR && type != IFREG && type != IFLNK) 21055460Sbostic panic("lfs_read type"); 21155460Sbostic if (type == IFLNK && (int)ip->i_size < vp->v_mount->mnt_maxsymlinklen) 21255460Sbostic panic("read short symlink"); 21348039Smckusick #endif 21453867Sheideman if (uio->uio_resid == 0) 21539608Smckusick return (0); 21655460Sbostic fs = ip->i_lfs; 21755460Sbostic if (uio->uio_offset < 0 || 21855460Sbostic (u_quad_t)uio->uio_offset + uio->uio_resid > fs->lfs_maxfilesize) 21955460Sbostic return (EFBIG); 22039608Smckusick ip->i_flag |= IACC; 22139608Smckusick do { 22253867Sheideman lbn = lblkno(fs, uio->uio_offset); 22353867Sheideman on = blkoff(fs, uio->uio_offset); 22455460Sbostic n = min((unsigned)(fs->lfs_bsize - on), uio->uio_resid); 22553867Sheideman diff = ip->i_size - uio->uio_offset; 22639608Smckusick if (diff <= 0) 22739608Smckusick return (0); 22839608Smckusick if (diff < n) 22939608Smckusick n = diff; 23055460Sbostic size = blksize(fs); 23139674Smckusick rablock = lbn + 1; 232*55936Sbostic lfs_check(vp, lbn); 23355460Sbostic if (vp->v_lastr + 1 == lbn && 23439896Smckusick lblktosize(fs, rablock) < ip->i_size) 23552195Smckusick error = breadn(ITOV(ip), lbn, size, &rablock, 23652195Smckusick &size, 1, NOCRED, &bp); 23739608Smckusick else 23839674Smckusick error = bread(ITOV(ip), lbn, size, NOCRED, &bp); 23955460Sbostic vp->v_lastr = lbn; 24055460Sbostic n = min(n, size - bp->b_resid); 24139608Smckusick if (error) { 24239608Smckusick brelse(bp); 24339608Smckusick return (error); 24439608Smckusick } 24553867Sheideman error = uiomove(bp->b_un.b_addr + on, (int)n, uio); 24653867Sheideman if (n + on == fs->lfs_bsize || uio->uio_offset == ip->i_size) 24739608Smckusick bp->b_flags |= B_AGE; 24839608Smckusick brelse(bp); 24953867Sheideman } while (error == 0 && uio->uio_resid > 0 && n != 0); 25039608Smckusick return (error); 25139608Smckusick } 25239608Smckusick 25339608Smckusick /* 25439608Smckusick * Vnode op for writing. 25539608Smckusick */ 25654030Smckusick lfs_write(ap) 25754692Sbostic struct vop_write_args /* { 25854692Sbostic struct vnode *a_vp; 25954692Sbostic struct uio *a_uio; 26054692Sbostic int a_ioflag; 26154692Sbostic struct ucred *a_cred; 26254692Sbostic } */ *ap; 26339608Smckusick { 26453867Sheideman register struct vnode *vp = ap->a_vp; 26554030Smckusick register struct uio *uio = ap->a_uio; 26654030Smckusick struct proc *p = uio->uio_procp; 26753867Sheideman register struct inode *ip = VTOI(vp); 26852091Sbostic register struct lfs *fs; 26954030Smckusick register ioflag = ap->a_ioflag; 27054765Smckusick struct timeval tv; 27139608Smckusick struct buf *bp; 27252091Sbostic daddr_t lbn; 27353233Smckusick off_t osize; 27452091Sbostic int n, on, flags, newblock; 27545722Smckusick int size, resid, error = 0; 27639608Smckusick 27748039Smckusick #ifdef DIAGNOSTIC 27854030Smckusick if (uio->uio_rw != UIO_WRITE) 27952091Sbostic panic("lfs_write mode"); 28048039Smckusick #endif 28153867Sheideman switch (vp->v_type) { 28239608Smckusick case VREG: 28354030Smckusick if (ioflag & IO_APPEND) 28454030Smckusick uio->uio_offset = ip->i_size; 28539608Smckusick /* fall through */ 28639608Smckusick case VLNK: 28739608Smckusick break; 28839608Smckusick 28939608Smckusick case VDIR: 29052091Sbostic /* XXX This may not be correct for LFS. */ 29154030Smckusick if ((ioflag & IO_SYNC) == 0) 29252091Sbostic panic("lfs_write nonsync dir write"); 29339608Smckusick break; 29439608Smckusick 29539608Smckusick default: 29652091Sbostic panic("lfs_write type"); 29739608Smckusick } 29854030Smckusick if (uio->uio_offset < 0) 29939608Smckusick return (EINVAL); 30054030Smckusick if (uio->uio_resid == 0) 30139608Smckusick return (0); 30239608Smckusick /* 30339608Smckusick * Maybe this should be above the vnode op call, but so long as 30439608Smckusick * file servers have no limits, i don't think it matters 30539608Smckusick */ 30653867Sheideman if (vp->v_type == VREG && p && 30754030Smckusick uio->uio_offset + uio->uio_resid > 30847571Skarels p->p_rlimit[RLIMIT_FSIZE].rlim_cur) { 30947571Skarels psignal(p, SIGXFSZ); 31039608Smckusick return (EFBIG); 31139608Smckusick } 31254030Smckusick resid = uio->uio_resid; 31339608Smckusick osize = ip->i_size; 31451183Sbostic fs = ip->i_lfs; /* LFS */ 31555460Sbostic if (uio->uio_offset < 0 || 31655460Sbostic (u_quad_t)uio->uio_offset + uio->uio_resid > fs->lfs_maxfilesize) 31755460Sbostic return (EFBIG); 31839608Smckusick do { 31954030Smckusick lbn = lblkno(fs, uio->uio_offset); 32054030Smckusick on = blkoff(fs, uio->uio_offset); 32155460Sbostic n = min((unsigned)(fs->lfs_bsize - on), uio->uio_resid); 322*55936Sbostic lfs_check(vp, lbn); 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); 33155460Sbostic n = min(n, size - bp->b_resid); 33254030Smckusick error = uiomove(bp->b_un.b_addr + on, n, uio); 333*55936Sbostic if (!error) 334*55936Sbostic error = VOP_BWRITE(bp); 33553593Sheideman if (ap->a_cred->cr_uid != 0) 33639608Smckusick ip->i_mode &= ~(ISUID|ISGID); 33754030Smckusick } while (error == 0 && uio->uio_resid > 0 && n != 0); 338*55936Sbostic if (error) { 339*55936Sbostic if (ioflag & IO_UNIT) { 340*55936Sbostic (void)VOP_TRUNCATE(vp, osize, ioflag & IO_SYNC, 341*55936Sbostic ap->a_cred, uio->uio_procp); 342*55936Sbostic uio->uio_offset -= resid - uio->uio_resid; 343*55936Sbostic uio->uio_resid = resid; 344*55936Sbostic } 345*55936Sbostic if (bp) 346*55936Sbostic brelse(bp); 34739608Smckusick } 34854765Smckusick if (!error && (ioflag & IO_SYNC)) { 34954765Smckusick tv = time; 350*55936Sbostic if (!(error = VOP_UPDATE(vp, &tv, &tv, 1))) 351*55936Sbostic error = VOP_FSYNC(vp, ap->a_cred, MNT_WAIT, 352*55936Sbostic uio->uio_procp); 35354765Smckusick } 35439608Smckusick return (error); 35539608Smckusick } 35639608Smckusick 3579167Ssam /* 35837737Smckusick * Synch an open file. 3599167Ssam */ 36037737Smckusick /* ARGSUSED */ 36154030Smckusick lfs_fsync(ap) 36254692Sbostic struct vop_fsync_args /* { 36354692Sbostic struct vnode *a_vp; 36454692Sbostic struct ucred *a_cred; 36554692Sbostic int a_waitfor; 36654692Sbostic struct proc *a_p; 36754692Sbostic } */ *ap; 3687701Ssam { 36954765Smckusick struct timeval tv; 3707701Ssam 37154765Smckusick tv = time; 37255547Sbostic return (VOP_UPDATE(ap->a_vp, &tv, &tv, 37355547Sbostic ap->a_waitfor == MNT_WAIT ? LFS_SYNC : 0)); 37437737Smckusick } 37551558Smckusick 37651558Smckusick /* 37751558Smckusick * Last reference to an inode, write the inode out and if necessary, 37851558Smckusick * truncate and deallocate the file. 37951558Smckusick */ 38051558Smckusick int 38154030Smckusick lfs_inactive(ap) 38254692Sbostic struct vop_inactive_args /* { 38354692Sbostic struct vnode *a_vp; 38454692Sbostic } */ *ap; 38551558Smckusick { 38651852Sbostic extern int prtactive; 38754030Smckusick register struct vnode *vp = ap->a_vp; 38851558Smckusick register struct inode *ip; 38954765Smckusick struct timeval tv; 39051558Smckusick int mode, error; 39151558Smckusick 39254030Smckusick if (prtactive && vp->v_usecount != 0) 39354030Smckusick vprint("lfs_inactive: pushing active", vp); 39451558Smckusick 39551558Smckusick /* Get rid of inodes related to stale file handles. */ 39654030Smckusick ip = VTOI(vp); 39751558Smckusick if (ip->i_mode == 0) { 39854030Smckusick if ((vp->v_flag & VXLOCK) == 0) 39954030Smckusick vgone(vp); 40051558Smckusick return (0); 40151558Smckusick } 40251558Smckusick 40351558Smckusick error = 0; 40451558Smckusick ILOCK(ip); 40554030Smckusick if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 40651558Smckusick #ifdef QUOTA 40751558Smckusick if (!getinoquota(ip)) 40851558Smckusick (void)chkiq(ip, -1, NOCRED, 0); 40951558Smckusick #endif 41054692Sbostic error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, NULL); 41151558Smckusick mode = ip->i_mode; 41251558Smckusick ip->i_mode = 0; 41351558Smckusick ip->i_rdev = 0; 41451558Smckusick ip->i_flag |= IUPD|ICHG; 41554030Smckusick VOP_VFREE(vp, ip->i_number, mode); 41651558Smckusick } 41754765Smckusick if (ip->i_flag&(IUPD|IACC|ICHG|IMOD)) { 41854765Smckusick tv = time; 41954765Smckusick VOP_UPDATE(vp, &tv, &tv, 0); 42054765Smckusick } 42151558Smckusick IUNLOCK(ip); 42251558Smckusick /* 42351558Smckusick * If we are done with the inode, reclaim it 42451558Smckusick * so that it can be reused immediately. 42551558Smckusick */ 42654030Smckusick if (vp->v_usecount == 0 && ip->i_mode == 0) 42754030Smckusick vgone(vp); 42851558Smckusick return (error); 42951558Smckusick } 43054264Sbostic 43154264Sbostic /* 43254264Sbostic * These macros are used to bracket UFS directory ops, so that we can 43354264Sbostic * identify all the pages touched during directory ops which need to 43454264Sbostic * be ordered and flushed atomically, so that they may be recovered. 43554264Sbostic */ 43654264Sbostic #define SET_DIROP(fs) { \ 43754264Sbostic if ((fs)->lfs_writer) \ 43855547Sbostic tsleep(&(fs)->lfs_dirops, PRIBIO + 1, "lfs_dirop", 0); \ 43954264Sbostic ++(fs)->lfs_dirops; \ 44054264Sbostic (fs)->lfs_doifile = 1; \ 44154264Sbostic } 44254264Sbostic 44354264Sbostic #define SET_ENDOP(fs) { \ 44454264Sbostic --(fs)->lfs_dirops; \ 44554264Sbostic if (!(fs)->lfs_dirops) \ 44654264Sbostic wakeup(&(fs)->lfs_writer); \ 44754264Sbostic } 44854264Sbostic 44954264Sbostic #define MARK_VNODE(dvp) (dvp)->v_flag |= VDIROP 45054264Sbostic 45154264Sbostic int 45254264Sbostic lfs_symlink(ap) 45354692Sbostic struct vop_symlink_args /* { 45454692Sbostic struct vnode *a_dvp; 45554692Sbostic struct vnode **a_vpp; 45654692Sbostic struct componentname *a_cnp; 45754692Sbostic struct vattr *a_vap; 45854692Sbostic char *a_target; 45954692Sbostic } */ *ap; 46054264Sbostic { 46154264Sbostic int ret; 46254264Sbostic 46354264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 46454264Sbostic MARK_VNODE(ap->a_dvp); 46554264Sbostic ret = ufs_symlink(ap); 46654264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 46754264Sbostic return (ret); 46854264Sbostic } 46954264Sbostic 47054264Sbostic int 47154264Sbostic lfs_mknod(ap) 47254692Sbostic struct vop_mknod_args /* { 47354692Sbostic struct vnode *a_dvp; 47454692Sbostic struct vnode **a_vpp; 47554692Sbostic struct componentname *a_cnp; 47654692Sbostic struct vattr *a_vap; 47754692Sbostic } */ *ap; 47854264Sbostic { 47954264Sbostic int ret; 48054264Sbostic 48154264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 48254264Sbostic MARK_VNODE(ap->a_dvp); 48354264Sbostic ret = ufs_mknod(ap); 48454264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 48554264Sbostic return (ret); 48654264Sbostic } 48754264Sbostic 48854264Sbostic int 48954264Sbostic lfs_create(ap) 49054692Sbostic struct vop_create_args /* { 49154692Sbostic struct vnode *a_dvp; 49254692Sbostic struct vnode **a_vpp; 49354692Sbostic struct componentname *a_cnp; 49454692Sbostic struct vattr *a_vap; 49554692Sbostic } */ *ap; 49654264Sbostic { 49754264Sbostic int ret; 49854264Sbostic 49954264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 50054264Sbostic MARK_VNODE(ap->a_dvp); 50154264Sbostic ret = ufs_create(ap); 50254264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 50354264Sbostic return (ret); 50454264Sbostic } 50554264Sbostic 50654264Sbostic int 50754264Sbostic lfs_mkdir(ap) 50854692Sbostic struct vop_mkdir_args /* { 50954692Sbostic struct vnode *a_dvp; 51054692Sbostic struct vnode **a_vpp; 51154692Sbostic struct componentname *a_cnp; 51254692Sbostic struct vattr *a_vap; 51354692Sbostic } */ *ap; 51454264Sbostic { 51554264Sbostic int ret; 51654264Sbostic 51754264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 51854264Sbostic MARK_VNODE(ap->a_dvp); 51954264Sbostic ret = ufs_mkdir(ap); 52054264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 52154264Sbostic return (ret); 52254264Sbostic } 52354264Sbostic 52454264Sbostic int 52554264Sbostic lfs_remove(ap) 52654692Sbostic struct vop_remove_args /* { 52754692Sbostic struct vnode *a_dvp; 52854692Sbostic struct vnode *a_vp; 52954692Sbostic struct componentname *a_cnp; 53054692Sbostic } */ *ap; 53154264Sbostic { 53254264Sbostic int ret; 53354264Sbostic 53454264Sbostic SET_DIROP(VTOI(ap->a_dvp)->i_lfs); 53554264Sbostic MARK_VNODE(ap->a_dvp); 53654264Sbostic MARK_VNODE(ap->a_vp); 53754264Sbostic ret = ufs_remove(ap); 53854264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 53954264Sbostic return (ret); 54054264Sbostic } 54154264Sbostic 54254264Sbostic int 54354264Sbostic lfs_rmdir(ap) 54454692Sbostic struct vop_rmdir_args /* { 54554692Sbostic struct vnodeop_desc *a_desc; 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_rmdir(ap); 55754264Sbostic SET_ENDOP(VTOI(ap->a_dvp)->i_lfs); 55854264Sbostic return (ret); 55954264Sbostic } 56054264Sbostic 56154264Sbostic int 56254264Sbostic lfs_link(ap) 56354692Sbostic struct vop_link_args /* { 56454692Sbostic struct vnode *a_vp; 56554692Sbostic struct vnode *a_tdvp; 56654692Sbostic struct componentname *a_cnp; 56754692Sbostic } */ *ap; 56854264Sbostic { 56954264Sbostic int ret; 57054264Sbostic 57154264Sbostic SET_DIROP(VTOI(ap->a_vp)->i_lfs); 57254264Sbostic MARK_VNODE(ap->a_vp); 57354264Sbostic ret = ufs_link(ap); 57454264Sbostic SET_ENDOP(VTOI(ap->a_vp)->i_lfs); 57554264Sbostic return (ret); 57654264Sbostic } 57754264Sbostic 57854264Sbostic int 57954264Sbostic lfs_rename(ap) 58054692Sbostic struct vop_rename_args /* { 58154692Sbostic struct vnode *a_fdvp; 58254692Sbostic struct vnode *a_fvp; 58354692Sbostic struct componentname *a_fcnp; 58454692Sbostic struct vnode *a_tdvp; 58554692Sbostic struct vnode *a_tvp; 58654692Sbostic struct componentname *a_tcnp; 58754692Sbostic } */ *ap; 58854264Sbostic { 58954264Sbostic int ret; 59054264Sbostic 59154264Sbostic SET_DIROP(VTOI(ap->a_fdvp)->i_lfs); 59254264Sbostic MARK_VNODE(ap->a_fdvp); 59354264Sbostic MARK_VNODE(ap->a_tdvp); 59454264Sbostic ret = ufs_rename(ap); 59554264Sbostic SET_ENDOP(VTOI(ap->a_fdvp)->i_lfs); 59654264Sbostic return (ret); 59754264Sbostic } 598*55936Sbostic /* XXX hack to avoid calling ITIMES in getattr */ 599*55936Sbostic int 600*55936Sbostic lfs_getattr(ap) 601*55936Sbostic struct vop_getattr_args /* { 602*55936Sbostic struct vnode *a_vp; 603*55936Sbostic struct vattr *a_vap; 604*55936Sbostic struct ucred *a_cred; 605*55936Sbostic struct proc *a_p; 606*55936Sbostic } */ *ap; 607*55936Sbostic { 608*55936Sbostic register struct vnode *vp = ap->a_vp; 609*55936Sbostic register struct inode *ip = VTOI(vp); 610*55936Sbostic register struct vattr *vap = ap->a_vap; 611*55936Sbostic /* 612*55936Sbostic * Copy from inode table 613*55936Sbostic */ 614*55936Sbostic vap->va_fsid = ip->i_dev; 615*55936Sbostic vap->va_fileid = ip->i_number; 616*55936Sbostic vap->va_mode = ip->i_mode & ~IFMT; 617*55936Sbostic vap->va_nlink = ip->i_nlink; 618*55936Sbostic vap->va_uid = ip->i_uid; 619*55936Sbostic vap->va_gid = ip->i_gid; 620*55936Sbostic vap->va_rdev = (dev_t)ip->i_rdev; 621*55936Sbostic vap->va_size = ip->i_din.di_size; 622*55936Sbostic vap->va_atime = ip->i_atime; 623*55936Sbostic vap->va_mtime = ip->i_mtime; 624*55936Sbostic vap->va_ctime = ip->i_ctime; 625*55936Sbostic vap->va_flags = ip->i_flags; 626*55936Sbostic vap->va_gen = ip->i_gen; 627*55936Sbostic /* this doesn't belong here */ 628*55936Sbostic if (vp->v_type == VBLK) 629*55936Sbostic vap->va_blocksize = BLKDEV_IOSIZE; 630*55936Sbostic else if (vp->v_type == VCHR) 631*55936Sbostic vap->va_blocksize = MAXBSIZE; 632*55936Sbostic else 633*55936Sbostic vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize; 634*55936Sbostic vap->va_bytes = dbtob(ip->i_blocks); 635*55936Sbostic vap->va_type = vp->v_type; 636*55936Sbostic vap->va_filerev = ip->i_modrev; 637*55936Sbostic return (0); 638*55936Sbostic } 639