1 /* 2 * Copyright (c) 1986, 1989, 1991 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)lfs_inode.c 7.48 (Berkeley) 11/08/91 8 */ 9 10 #include <sys/param.h> 11 #include <sys/systm.h> 12 #include <sys/mount.h> 13 #include <sys/proc.h> 14 #include <sys/file.h> 15 #include <sys/buf.h> 16 #include <sys/vnode.h> 17 #include <sys/kernel.h> 18 #include <sys/malloc.h> 19 20 #include <ufs/ufs/quota.h> 21 #include <ufs/ufs/inode.h> 22 #include <ufs/ufs/ufsmount.h> 23 #include <ufs/ufs/ufs_extern.h> 24 25 #include <ufs/lfs/lfs.h> 26 #include <ufs/lfs/lfs_extern.h> 27 28 int 29 lfs_init() 30 { 31 return (ufs_init()); 32 } 33 34 /* 35 * Look up an LFS dinode number to find its incore vnode. If not already 36 * in core, read it in from the specified device. Return the inode locked. 37 * Detection and handling of mount points must be done by the calling routine. 38 */ 39 int 40 lfs_vget(mntp, ino, vpp) 41 struct mount *mntp; 42 ino_t ino; 43 struct vnode **vpp; 44 { 45 register struct lfs *fs; 46 register struct inode *ip; 47 struct buf *bp; 48 struct vnode *vp; 49 struct ufsmount *ump; 50 dev_t dev; 51 int error; 52 53 ump = VFSTOUFS(mntp); 54 dev = ump->um_dev; 55 if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 56 return (0); 57 58 /* Allocate new vnode/inode. */ 59 if (error = lfs_vcreate(mntp, ino, &vp)) { 60 *vpp = NULL; 61 return (error); 62 } 63 /* 64 * Put it onto its hash chain and lock it so that other requests for 65 * this inode will block if they arrive while we are sleeping waiting 66 * for old data structures to be purged or for the contents of the 67 * disk portion of this inode to be read. 68 */ 69 ip = VTOI(vp); 70 ufs_ihashins(ip); 71 72 /* Read in the disk contents for the inode, copy into the inode. */ 73 fs = ump->um_lfs; 74 if (error = bread(ump->um_devvp, lfs_itod(fs, ino), 75 (int)fs->lfs_bsize, NOCRED, &bp)) { 76 /* 77 * The inode does not contain anything useful, so it would 78 * be misleading to leave it on its hash chain. Iput() will 79 * return it to the free list. 80 */ 81 remque(ip); 82 ip->i_forw = ip; 83 ip->i_back = ip; 84 85 /* Unlock and discard unneeded inode. */ 86 ufs_iput(ip); 87 brelse(bp); 88 *vpp = NULL; 89 return (error); 90 } 91 ip->i_din = *lfs_ifind(fs, ino, bp->b_un.b_dino); 92 brelse(bp); 93 94 /* 95 * Initialize the vnode from the inode, check for aliases. In all 96 * cases re-init ip, the underlying vnode/inode may have changed. 97 */ 98 if (error = ufs_vinit(mntp, &lfs_specops, LFS_FIFOOPS, &vp)) { 99 ufs_iput(ip); 100 *vpp = NULL; 101 return (error); 102 } 103 /* 104 * Finish inode initialization now that aliasing has been resolved. 105 */ 106 ip = VTOI(vp); 107 ip->i_lfs = ump->um_lfs; 108 ip->i_devvp = ump->um_devvp; 109 VREF(ip->i_devvp); 110 *vpp = vp; 111 return (0); 112 } 113 114 int 115 lfs_update(vp, ta, tm, waitfor) 116 register struct vnode *vp; 117 struct timeval *ta, *tm; 118 int waitfor; 119 { 120 struct inode *ip; 121 122 if (vp->v_mount->mnt_flag & MNT_RDONLY) 123 return (0); 124 ip = VTOI(vp); 125 if ((ip->i_flag & (IUPD|IACC|ICHG|IMOD)) == 0) 126 return (0); 127 if (ip->i_flag&IACC) 128 ip->i_atime = ta->tv_sec; 129 if (ip->i_flag&IUPD) 130 ip->i_mtime = tm->tv_sec; 131 if (ip->i_flag&ICHG) 132 ip->i_ctime = time.tv_sec; 133 ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD); 134 135 /* 136 * XXX 137 * I'm not real sure what to do here; once we have fsync and partial 138 * segments working in the LFS context, this must be fixed to be 139 * correct. The contents of the inode have to be pushed back to 140 * stable storage; note that the ifile contains the access time of 141 * the inode and must be updated as well. 142 */ 143 return (0); 144 } 145 146 /* 147 * Truncate the inode ip to at most length size. 148 * 149 * NB: triple indirect blocks are untested. 150 */ 151 /* ARGSUSED */ 152 int 153 lfs_truncate(ovp, length, flags) 154 struct vnode *ovp; 155 u_long length; 156 int flags; 157 { 158 register struct lfs *fs; 159 register struct inode *oip; 160 struct buf *bp; 161 daddr_t lbn; 162 int error, offset, size; 163 164 vnode_pager_setsize(ovp, length); 165 oip = VTOI(ovp); 166 167 /* If length is larger than the file, just update the times. */ 168 if (oip->i_size <= length) { 169 oip->i_flag |= ICHG|IUPD; 170 ITIMES(oip, &time, &time); 171 return (0); 172 } 173 174 /* 175 * Update the size of the file. If the file is not being truncated to 176 * a block boundry, the contents of the partial block following the end 177 * of the file must be zero'ed in case it ever become accessable again 178 * because of subsequent file growth. 179 */ 180 fs = oip->i_lfs; 181 offset = blkoff(fs, length); 182 if (offset == 0) 183 oip->i_size = length; 184 else { 185 lbn = lblkno(fs, length); 186 #ifdef QUOTA 187 if (error = getinoquota(oip)) 188 return (error); 189 #endif 190 if (error = bread(ovp, lbn, fs->lfs_bsize, NOCRED, &bp)) 191 return (error); 192 oip->i_size = length; 193 size = blksize(fs); /* LFS */ 194 (void) vnode_pager_uncache(ovp); 195 bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset)); 196 allocbuf(bp, size); 197 lfs_bwrite(bp); 198 } 199 /* BZERO INODE BLOCK POINTERS HERE, FOR CONSISTENCY XXX */ 200 } 201