123399Smckusick /* 251498Sbostic * Copyright (c) 1986, 1989, 1991 Regents of the University of California. 337736Smckusick * All rights reserved. 423399Smckusick * 544537Sbostic * %sccs.include.redist.c% 637736Smckusick * 7*52078Sbostic * @(#)lfs_inode.c 7.51 (Berkeley) 12/30/91 823399Smckusick */ 924Sbill 1051484Sbostic #include <sys/param.h> 1151484Sbostic #include <sys/systm.h> 1251484Sbostic #include <sys/mount.h> 1351484Sbostic #include <sys/proc.h> 1451484Sbostic #include <sys/file.h> 1551484Sbostic #include <sys/buf.h> 1651484Sbostic #include <sys/vnode.h> 1751484Sbostic #include <sys/kernel.h> 1851484Sbostic #include <sys/malloc.h> 1924Sbill 2051498Sbostic #include <ufs/ufs/quota.h> 2151498Sbostic #include <ufs/ufs/inode.h> 2251498Sbostic #include <ufs/ufs/ufsmount.h> 2351498Sbostic #include <ufs/ufs/ufs_extern.h> 2447571Skarels 2551498Sbostic #include <ufs/lfs/lfs.h> 2651498Sbostic #include <ufs/lfs/lfs_extern.h> 2724Sbill 2851346Sbostic int 2951155Sbostic lfs_init() 3024Sbill { 3151857Sbostic #ifdef VERBOSE 3251857Sbostic printf("lfs_init\n"); 3351857Sbostic #endif 3451484Sbostic return (ufs_init()); 3524Sbill } 3624Sbill 3724Sbill /* 3851484Sbostic * Look up an LFS dinode number to find its incore vnode. If not already 3951484Sbostic * in core, read it in from the specified device. Return the inode locked. 4051484Sbostic * Detection and handling of mount points must be done by the calling routine. 4124Sbill */ 4251346Sbostic int 4351562Smckusick lfs_vget(mntp, ino, vpp) 4451562Smckusick struct mount *mntp; 454818Swnj ino_t ino; 4651562Smckusick struct vnode **vpp; 4724Sbill { 4851498Sbostic register struct lfs *fs; 4951484Sbostic register struct inode *ip; 5051484Sbostic struct buf *bp; 5151498Sbostic struct vnode *vp; 5251562Smckusick struct ufsmount *ump; 5351484Sbostic dev_t dev; 5451346Sbostic int error; 5524Sbill 5651857Sbostic #ifdef VERBOSE 5751857Sbostic printf("lfs_vget\n"); 5851857Sbostic #endif 5951562Smckusick ump = VFSTOUFS(mntp); 6051562Smckusick dev = ump->um_dev; 6151562Smckusick if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 6251484Sbostic return (0); 6351484Sbostic 6451155Sbostic /* Allocate new vnode/inode. */ 6551498Sbostic if (error = lfs_vcreate(mntp, ino, &vp)) { 6651562Smckusick *vpp = NULL; 6737736Smckusick return (error); 6837736Smckusick } 6937736Smckusick /* 7039440Smckusick * Put it onto its hash chain and lock it so that other requests for 7139440Smckusick * this inode will block if they arrive while we are sleeping waiting 7239440Smckusick * for old data structures to be purged or for the contents of the 7339440Smckusick * disk portion of this inode to be read. 7439440Smckusick */ 7551562Smckusick ip = VTOI(vp); 7651484Sbostic ufs_ihashins(ip); 7751155Sbostic 7851484Sbostic /* Read in the disk contents for the inode, copy into the inode. */ 7952018Smckusick ip->i_lfs = fs = ump->um_lfs; 8051562Smckusick if (error = bread(ump->um_devvp, lfs_itod(fs, ino), 8151484Sbostic (int)fs->lfs_bsize, NOCRED, &bp)) { 8237736Smckusick /* 8351857Sbostic * The inode does not contain anything useful, so it 8451857Sbostic * would be misleading to leave it on its hash chain. 8551857Sbostic * Iput() will return it to the free list. 8641334Smckusick */ 8741334Smckusick remque(ip); 8841334Smckusick ip->i_forw = ip; 8941334Smckusick ip->i_back = ip; 9051484Sbostic 9151484Sbostic /* Unlock and discard unneeded inode. */ 9251484Sbostic ufs_iput(ip); 9337736Smckusick brelse(bp); 9451562Smckusick *vpp = NULL; 9539440Smckusick return (error); 9637736Smckusick } 9751155Sbostic ip->i_din = *lfs_ifind(fs, ino, bp->b_un.b_dino); 9839440Smckusick brelse(bp); 9951155Sbostic 10051498Sbostic /* 10151498Sbostic * Initialize the vnode from the inode, check for aliases. In all 10251498Sbostic * cases re-init ip, the underlying vnode/inode may have changed. 10351498Sbostic */ 10451595Smckusick if (error = ufs_vinit(mntp, &lfs_specops, LFS_FIFOOPS, &vp)) { 10551484Sbostic ufs_iput(ip); 10651562Smckusick *vpp = NULL; 10751484Sbostic return (error); 10840289Smckusick } 10951562Smckusick /* 11051562Smckusick * Finish inode initialization now that aliasing has been resolved. 11151562Smckusick */ 11251562Smckusick ip->i_devvp = ump->um_devvp; 11351562Smckusick VREF(ip->i_devvp); 11451562Smckusick *vpp = vp; 11537736Smckusick return (0); 11637736Smckusick } 1177334Skre 11851346Sbostic int 11951562Smckusick lfs_update(vp, ta, tm, waitfor) 12051562Smckusick register struct vnode *vp; 12151484Sbostic struct timeval *ta, *tm; 12251484Sbostic int waitfor; 1237118Smckusick { 12451562Smckusick struct inode *ip; 12551562Smckusick 12651857Sbostic #ifdef VERBOSE 12751857Sbostic printf("lfs_update\n"); 12851857Sbostic #endif 12951562Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 13051562Smckusick return (0); 13151562Smckusick ip = VTOI(vp); 13251562Smckusick if ((ip->i_flag & (IUPD|IACC|ICHG|IMOD)) == 0) 13351562Smckusick return (0); 13451562Smckusick if (ip->i_flag&IACC) 13551562Smckusick ip->i_atime = ta->tv_sec; 13652018Smckusick if (ip->i_flag&IUPD) { 13751562Smckusick ip->i_mtime = tm->tv_sec; 13852018Smckusick INCRQUAD((ip)->i_modrev); 13952018Smckusick } 14051562Smckusick if (ip->i_flag&ICHG) 14151562Smckusick ip->i_ctime = time.tv_sec; 14251562Smckusick ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD); 14351562Smckusick 14438452Smckusick /* 14551484Sbostic * XXX 14651562Smckusick * I'm not real sure what to do here; once we have fsync and partial 14751562Smckusick * segments working in the LFS context, this must be fixed to be 14851562Smckusick * correct. The contents of the inode have to be pushed back to 149*52078Sbostic * stable storage. 15038452Smckusick */ 15151484Sbostic return (0); 15224Sbill } 15324Sbill 15424Sbill /* 15551484Sbostic * Truncate the inode ip to at most length size. 15610736Ssam * 15710736Ssam * NB: triple indirect blocks are untested. 15824Sbill */ 15951484Sbostic /* ARGSUSED */ 16051484Sbostic int 16151562Smckusick lfs_truncate(ovp, length, flags) 16251562Smckusick struct vnode *ovp; 1639165Ssam u_long length; 16439676Smckusick int flags; 16524Sbill { 16651498Sbostic register struct lfs *fs; 16751562Smckusick register struct inode *oip; 16817942Smckusick struct buf *bp; 16951484Sbostic daddr_t lbn; 17051484Sbostic int error, offset, size; 1719165Ssam 17251857Sbostic #ifdef VERBOSE 17351857Sbostic printf("lfs_truncate\n"); 17451857Sbostic #endif 17551562Smckusick vnode_pager_setsize(ovp, length); 17651562Smckusick oip = VTOI(ovp); 17751484Sbostic 17851484Sbostic /* If length is larger than the file, just update the times. */ 17913000Ssam if (oip->i_size <= length) { 18013000Ssam oip->i_flag |= ICHG|IUPD; 18151183Sbostic ITIMES(oip, &time, &time); 18251183Sbostic return (0); 18313000Ssam } 18451484Sbostic 1851203Sbill /* 18651484Sbostic * Update the size of the file. If the file is not being truncated to 18751484Sbostic * a block boundry, the contents of the partial block following the end 18851484Sbostic * of the file must be zero'ed in case it ever become accessable again 18951484Sbostic * because of subsequent file growth. 1901203Sbill */ 19151484Sbostic fs = oip->i_lfs; 19217942Smckusick offset = blkoff(fs, length); 19351484Sbostic if (offset == 0) 19417942Smckusick oip->i_size = length; 19551484Sbostic else { 19617942Smckusick lbn = lblkno(fs, length); 19741313Smckusick #ifdef QUOTA 19841313Smckusick if (error = getinoquota(oip)) 19941313Smckusick return (error); 20051183Sbostic #endif 20151562Smckusick if (error = bread(ovp, lbn, fs->lfs_bsize, NOCRED, &bp)) 20237736Smckusick return (error); 20317942Smckusick oip->i_size = length; 20451857Sbostic size = blksize(fs); 20551857Sbostic (void)vnode_pager_uncache(ovp); 20626272Skarels bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset)); 20745112Smckusick allocbuf(bp, size); 208*52078Sbostic LFS_UBWRITE(bp); 20917942Smckusick } 210*52078Sbostic /* 211*52078Sbostic * XXX 212*52078Sbostic * Bzero inode block pointers here, for consistency with ffs. 213*52078Sbostic * Segment usage information has to be updated when the blocks 214*52078Sbostic * are free. 215*52078Sbostic * Block count in the inode has to be fixed when blocks are 216*52078Sbostic * free. 217*52078Sbostic */ 21851857Sbostic (void)vinvalbuf(ovp, length > 0); 21951857Sbostic return (0); 22024Sbill } 221