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*51595Smckusick * @(#)lfs_inode.c 7.48 (Berkeley) 11/08/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 { 3151484Sbostic return (ufs_init()); 3224Sbill } 3324Sbill 3424Sbill /* 3551484Sbostic * Look up an LFS dinode number to find its incore vnode. If not already 3651484Sbostic * in core, read it in from the specified device. Return the inode locked. 3751484Sbostic * Detection and handling of mount points must be done by the calling routine. 3824Sbill */ 3951346Sbostic int 4051562Smckusick lfs_vget(mntp, ino, vpp) 4151562Smckusick struct mount *mntp; 424818Swnj ino_t ino; 4351562Smckusick struct vnode **vpp; 4424Sbill { 4551498Sbostic register struct lfs *fs; 4651484Sbostic register struct inode *ip; 4751484Sbostic struct buf *bp; 4851498Sbostic struct vnode *vp; 4951562Smckusick struct ufsmount *ump; 5051484Sbostic dev_t dev; 5151346Sbostic int error; 5224Sbill 5351562Smckusick ump = VFSTOUFS(mntp); 5451562Smckusick dev = ump->um_dev; 5551562Smckusick if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 5651484Sbostic return (0); 5751484Sbostic 5851155Sbostic /* Allocate new vnode/inode. */ 5951498Sbostic if (error = lfs_vcreate(mntp, ino, &vp)) { 6051562Smckusick *vpp = NULL; 6137736Smckusick return (error); 6237736Smckusick } 6337736Smckusick /* 6439440Smckusick * Put it onto its hash chain and lock it so that other requests for 6539440Smckusick * this inode will block if they arrive while we are sleeping waiting 6639440Smckusick * for old data structures to be purged or for the contents of the 6739440Smckusick * disk portion of this inode to be read. 6839440Smckusick */ 6951562Smckusick ip = VTOI(vp); 7051484Sbostic ufs_ihashins(ip); 7151155Sbostic 7251484Sbostic /* Read in the disk contents for the inode, copy into the inode. */ 7351562Smckusick fs = ump->um_lfs; 7451562Smckusick if (error = bread(ump->um_devvp, lfs_itod(fs, ino), 7551484Sbostic (int)fs->lfs_bsize, NOCRED, &bp)) { 7637736Smckusick /* 7741334Smckusick * The inode does not contain anything useful, so it would 7851484Sbostic * be misleading to leave it on its hash chain. Iput() will 7951498Sbostic * return it to the free list. 8041334Smckusick */ 8141334Smckusick remque(ip); 8241334Smckusick ip->i_forw = ip; 8341334Smckusick ip->i_back = ip; 8451484Sbostic 8551484Sbostic /* Unlock and discard unneeded inode. */ 8651484Sbostic ufs_iput(ip); 8737736Smckusick brelse(bp); 8851562Smckusick *vpp = NULL; 8939440Smckusick return (error); 9037736Smckusick } 9151155Sbostic ip->i_din = *lfs_ifind(fs, ino, bp->b_un.b_dino); 9239440Smckusick brelse(bp); 9351155Sbostic 9451498Sbostic /* 9551498Sbostic * Initialize the vnode from the inode, check for aliases. In all 9651498Sbostic * cases re-init ip, the underlying vnode/inode may have changed. 9751498Sbostic */ 98*51595Smckusick if (error = ufs_vinit(mntp, &lfs_specops, LFS_FIFOOPS, &vp)) { 9951484Sbostic ufs_iput(ip); 10051562Smckusick *vpp = NULL; 10151484Sbostic return (error); 10240289Smckusick } 10351562Smckusick /* 10451562Smckusick * Finish inode initialization now that aliasing has been resolved. 10551562Smckusick */ 10651562Smckusick ip = VTOI(vp); 10751562Smckusick ip->i_lfs = ump->um_lfs; 10851562Smckusick ip->i_devvp = ump->um_devvp; 10951562Smckusick VREF(ip->i_devvp); 11051562Smckusick *vpp = vp; 11137736Smckusick return (0); 11237736Smckusick } 1137334Skre 11451346Sbostic int 11551562Smckusick lfs_update(vp, ta, tm, waitfor) 11651562Smckusick register struct vnode *vp; 11751484Sbostic struct timeval *ta, *tm; 11851484Sbostic int waitfor; 1197118Smckusick { 12051562Smckusick struct inode *ip; 12151562Smckusick 12251562Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 12351562Smckusick return (0); 12451562Smckusick ip = VTOI(vp); 12551562Smckusick if ((ip->i_flag & (IUPD|IACC|ICHG|IMOD)) == 0) 12651562Smckusick return (0); 12751562Smckusick if (ip->i_flag&IACC) 12851562Smckusick ip->i_atime = ta->tv_sec; 12951562Smckusick if (ip->i_flag&IUPD) 13051562Smckusick ip->i_mtime = tm->tv_sec; 13151562Smckusick if (ip->i_flag&ICHG) 13251562Smckusick ip->i_ctime = time.tv_sec; 13351562Smckusick ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD); 13451562Smckusick 13538452Smckusick /* 13651484Sbostic * XXX 13751562Smckusick * I'm not real sure what to do here; once we have fsync and partial 13851562Smckusick * segments working in the LFS context, this must be fixed to be 13951562Smckusick * correct. The contents of the inode have to be pushed back to 14051562Smckusick * stable storage; note that the ifile contains the access time of 14151562Smckusick * the inode and must be updated as well. 14238452Smckusick */ 14351484Sbostic return (0); 14424Sbill } 14524Sbill 14624Sbill /* 14751484Sbostic * Truncate the inode ip to at most length size. 14810736Ssam * 14910736Ssam * NB: triple indirect blocks are untested. 15024Sbill */ 15151484Sbostic /* ARGSUSED */ 15251484Sbostic int 15351562Smckusick lfs_truncate(ovp, length, flags) 15451562Smckusick struct vnode *ovp; 1559165Ssam u_long length; 15639676Smckusick int flags; 15724Sbill { 15851498Sbostic register struct lfs *fs; 15951562Smckusick register struct inode *oip; 16017942Smckusick struct buf *bp; 16151484Sbostic daddr_t lbn; 16251484Sbostic int error, offset, size; 1639165Ssam 16451562Smckusick vnode_pager_setsize(ovp, length); 16551562Smckusick oip = VTOI(ovp); 16651484Sbostic 16751484Sbostic /* If length is larger than the file, just update the times. */ 16813000Ssam if (oip->i_size <= length) { 16913000Ssam oip->i_flag |= ICHG|IUPD; 17051183Sbostic ITIMES(oip, &time, &time); 17151183Sbostic return (0); 17213000Ssam } 17351484Sbostic 1741203Sbill /* 17551484Sbostic * Update the size of the file. If the file is not being truncated to 17651484Sbostic * a block boundry, the contents of the partial block following the end 17751484Sbostic * of the file must be zero'ed in case it ever become accessable again 17851484Sbostic * because of subsequent file growth. 1791203Sbill */ 18051484Sbostic fs = oip->i_lfs; 18117942Smckusick offset = blkoff(fs, length); 18251484Sbostic if (offset == 0) 18317942Smckusick oip->i_size = length; 18451484Sbostic else { 18517942Smckusick lbn = lblkno(fs, length); 18641313Smckusick #ifdef QUOTA 18741313Smckusick if (error = getinoquota(oip)) 18841313Smckusick return (error); 18951183Sbostic #endif 19051562Smckusick if (error = bread(ovp, lbn, fs->lfs_bsize, NOCRED, &bp)) 19137736Smckusick return (error); 19217942Smckusick oip->i_size = length; 19351155Sbostic size = blksize(fs); /* LFS */ 19451562Smckusick (void) vnode_pager_uncache(ovp); 19526272Skarels bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset)); 19645112Smckusick allocbuf(bp, size); 19751183Sbostic lfs_bwrite(bp); 19817942Smckusick } 19951484Sbostic /* BZERO INODE BLOCK POINTERS HERE, FOR CONSISTENCY XXX */ 20024Sbill } 201