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*51562Smckusick * @(#)lfs_inode.c 7.47 (Berkeley) 11/05/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 40*51562Smckusick lfs_vget(mntp, ino, vpp) 41*51562Smckusick struct mount *mntp; 424818Swnj ino_t ino; 43*51562Smckusick struct vnode **vpp; 4424Sbill { 4551498Sbostic register struct lfs *fs; 4651484Sbostic register struct inode *ip; 4751484Sbostic struct buf *bp; 4851498Sbostic struct vnode *vp; 49*51562Smckusick struct ufsmount *ump; 5051484Sbostic dev_t dev; 5151346Sbostic int error; 52*51562Smckusick extern struct vnodeops lfs_fifoops, lfs_specops; 5324Sbill 54*51562Smckusick ump = VFSTOUFS(mntp); 55*51562Smckusick dev = ump->um_dev; 56*51562Smckusick if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 5751484Sbostic return (0); 5851484Sbostic 5951155Sbostic /* Allocate new vnode/inode. */ 6051498Sbostic if (error = lfs_vcreate(mntp, ino, &vp)) { 61*51562Smckusick *vpp = NULL; 6237736Smckusick return (error); 6337736Smckusick } 6437736Smckusick /* 6539440Smckusick * Put it onto its hash chain and lock it so that other requests for 6639440Smckusick * this inode will block if they arrive while we are sleeping waiting 6739440Smckusick * for old data structures to be purged or for the contents of the 6839440Smckusick * disk portion of this inode to be read. 6939440Smckusick */ 70*51562Smckusick ip = VTOI(vp); 7151484Sbostic ufs_ihashins(ip); 7251155Sbostic 7351484Sbostic /* Read in the disk contents for the inode, copy into the inode. */ 74*51562Smckusick fs = ump->um_lfs; 75*51562Smckusick if (error = bread(ump->um_devvp, lfs_itod(fs, ino), 7651484Sbostic (int)fs->lfs_bsize, NOCRED, &bp)) { 7737736Smckusick /* 7841334Smckusick * The inode does not contain anything useful, so it would 7951484Sbostic * be misleading to leave it on its hash chain. Iput() will 8051498Sbostic * return it to the free list. 8141334Smckusick */ 8241334Smckusick remque(ip); 8341334Smckusick ip->i_forw = ip; 8441334Smckusick ip->i_back = ip; 8551484Sbostic 8651484Sbostic /* Unlock and discard unneeded inode. */ 8751484Sbostic ufs_iput(ip); 8837736Smckusick brelse(bp); 89*51562Smckusick *vpp = NULL; 9039440Smckusick return (error); 9137736Smckusick } 9251155Sbostic ip->i_din = *lfs_ifind(fs, ino, bp->b_un.b_dino); 9339440Smckusick brelse(bp); 9451155Sbostic 9551498Sbostic /* 9651498Sbostic * Initialize the vnode from the inode, check for aliases. In all 9751498Sbostic * cases re-init ip, the underlying vnode/inode may have changed. 9851498Sbostic */ 99*51562Smckusick if (error = ufs_vinit(mntp, &lfs_specops, &lfs_fifoops, &vp)) { 10051484Sbostic ufs_iput(ip); 101*51562Smckusick *vpp = NULL; 10251484Sbostic return (error); 10340289Smckusick } 104*51562Smckusick /* 105*51562Smckusick * Finish inode initialization now that aliasing has been resolved. 106*51562Smckusick */ 107*51562Smckusick ip = VTOI(vp); 108*51562Smckusick ip->i_lfs = ump->um_lfs; 109*51562Smckusick ip->i_devvp = ump->um_devvp; 110*51562Smckusick VREF(ip->i_devvp); 111*51562Smckusick *vpp = vp; 11237736Smckusick return (0); 11337736Smckusick } 1147334Skre 11551346Sbostic int 116*51562Smckusick lfs_update(vp, ta, tm, waitfor) 117*51562Smckusick register struct vnode *vp; 11851484Sbostic struct timeval *ta, *tm; 11951484Sbostic int waitfor; 1207118Smckusick { 121*51562Smckusick struct inode *ip; 122*51562Smckusick 123*51562Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 124*51562Smckusick return (0); 125*51562Smckusick ip = VTOI(vp); 126*51562Smckusick if ((ip->i_flag & (IUPD|IACC|ICHG|IMOD)) == 0) 127*51562Smckusick return (0); 128*51562Smckusick if (ip->i_flag&IACC) 129*51562Smckusick ip->i_atime = ta->tv_sec; 130*51562Smckusick if (ip->i_flag&IUPD) 131*51562Smckusick ip->i_mtime = tm->tv_sec; 132*51562Smckusick if (ip->i_flag&ICHG) 133*51562Smckusick ip->i_ctime = time.tv_sec; 134*51562Smckusick ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD); 135*51562Smckusick 13638452Smckusick /* 13751484Sbostic * XXX 138*51562Smckusick * I'm not real sure what to do here; once we have fsync and partial 139*51562Smckusick * segments working in the LFS context, this must be fixed to be 140*51562Smckusick * correct. The contents of the inode have to be pushed back to 141*51562Smckusick * stable storage; note that the ifile contains the access time of 142*51562Smckusick * the inode and must be updated as well. 14338452Smckusick */ 14451484Sbostic return (0); 14524Sbill } 14624Sbill 14724Sbill /* 14851484Sbostic * Truncate the inode ip to at most length size. 14910736Ssam * 15010736Ssam * NB: triple indirect blocks are untested. 15124Sbill */ 15251484Sbostic /* ARGSUSED */ 15351484Sbostic int 154*51562Smckusick lfs_truncate(ovp, length, flags) 155*51562Smckusick struct vnode *ovp; 1569165Ssam u_long length; 15739676Smckusick int flags; 15824Sbill { 15951498Sbostic register struct lfs *fs; 160*51562Smckusick register struct inode *oip; 16117942Smckusick struct buf *bp; 16251484Sbostic daddr_t lbn; 16351484Sbostic int error, offset, size; 1649165Ssam 165*51562Smckusick vnode_pager_setsize(ovp, length); 166*51562Smckusick oip = VTOI(ovp); 16751484Sbostic 16851484Sbostic /* If length is larger than the file, just update the times. */ 16913000Ssam if (oip->i_size <= length) { 17013000Ssam oip->i_flag |= ICHG|IUPD; 17151183Sbostic ITIMES(oip, &time, &time); 17251183Sbostic return (0); 17313000Ssam } 17451484Sbostic 1751203Sbill /* 17651484Sbostic * Update the size of the file. If the file is not being truncated to 17751484Sbostic * a block boundry, the contents of the partial block following the end 17851484Sbostic * of the file must be zero'ed in case it ever become accessable again 17951484Sbostic * because of subsequent file growth. 1801203Sbill */ 18151484Sbostic fs = oip->i_lfs; 18217942Smckusick offset = blkoff(fs, length); 18351484Sbostic if (offset == 0) 18417942Smckusick oip->i_size = length; 18551484Sbostic else { 18617942Smckusick lbn = lblkno(fs, length); 18741313Smckusick #ifdef QUOTA 18841313Smckusick if (error = getinoquota(oip)) 18941313Smckusick return (error); 19051183Sbostic #endif 191*51562Smckusick if (error = bread(ovp, lbn, fs->lfs_bsize, NOCRED, &bp)) 19237736Smckusick return (error); 19317942Smckusick oip->i_size = length; 19451155Sbostic size = blksize(fs); /* LFS */ 195*51562Smckusick (void) vnode_pager_uncache(ovp); 19626272Skarels bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset)); 19745112Smckusick allocbuf(bp, size); 19851183Sbostic lfs_bwrite(bp); 19917942Smckusick } 20051484Sbostic /* BZERO INODE BLOCK POINTERS HERE, FOR CONSISTENCY XXX */ 20124Sbill } 202