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*52018Smckusick * @(#)lfs_inode.c 7.50 (Berkeley) 12/19/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. */ 79*52018Smckusick 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; 136*52018Smckusick if (ip->i_flag&IUPD) { 13751562Smckusick ip->i_mtime = tm->tv_sec; 138*52018Smckusick INCRQUAD((ip)->i_modrev); 139*52018Smckusick } 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 14951562Smckusick * stable storage; note that the ifile contains the access time of 15051562Smckusick * the inode and must be updated as well. 15138452Smckusick */ 15251484Sbostic return (0); 15324Sbill } 15424Sbill 15524Sbill /* 15651484Sbostic * Truncate the inode ip to at most length size. 15710736Ssam * 15810736Ssam * NB: triple indirect blocks are untested. 15924Sbill */ 16051484Sbostic /* ARGSUSED */ 16151484Sbostic int 16251562Smckusick lfs_truncate(ovp, length, flags) 16351562Smckusick struct vnode *ovp; 1649165Ssam u_long length; 16539676Smckusick int flags; 16624Sbill { 16751498Sbostic register struct lfs *fs; 16851562Smckusick register struct inode *oip; 16917942Smckusick struct buf *bp; 17051484Sbostic daddr_t lbn; 17151484Sbostic int error, offset, size; 1729165Ssam 17351857Sbostic #ifdef VERBOSE 17451857Sbostic printf("lfs_truncate\n"); 17551857Sbostic #endif 17651562Smckusick vnode_pager_setsize(ovp, length); 17751562Smckusick oip = VTOI(ovp); 17851484Sbostic 17951484Sbostic /* If length is larger than the file, just update the times. */ 18013000Ssam if (oip->i_size <= length) { 18113000Ssam oip->i_flag |= ICHG|IUPD; 18251183Sbostic ITIMES(oip, &time, &time); 18351183Sbostic return (0); 18413000Ssam } 18551484Sbostic 1861203Sbill /* 18751484Sbostic * Update the size of the file. If the file is not being truncated to 18851484Sbostic * a block boundry, the contents of the partial block following the end 18951484Sbostic * of the file must be zero'ed in case it ever become accessable again 19051484Sbostic * because of subsequent file growth. 1911203Sbill */ 19251484Sbostic fs = oip->i_lfs; 19317942Smckusick offset = blkoff(fs, length); 19451484Sbostic if (offset == 0) 19517942Smckusick oip->i_size = length; 19651484Sbostic else { 19717942Smckusick lbn = lblkno(fs, length); 19841313Smckusick #ifdef QUOTA 19941313Smckusick if (error = getinoquota(oip)) 20041313Smckusick return (error); 20151183Sbostic #endif 20251562Smckusick if (error = bread(ovp, lbn, fs->lfs_bsize, NOCRED, &bp)) 20337736Smckusick return (error); 20417942Smckusick oip->i_size = length; 20551857Sbostic size = blksize(fs); 20651857Sbostic (void)vnode_pager_uncache(ovp); 20726272Skarels bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset)); 20845112Smckusick allocbuf(bp, size); 20951183Sbostic lfs_bwrite(bp); 21017942Smckusick } 21151857Sbostic /* XXX: BZERO INODE BLOCK POINTERS HERE, FOR CONSISTENCY. */ 21251857Sbostic (void)vinvalbuf(ovp, length > 0); 21351857Sbostic return (0); 21424Sbill } 215