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.47 (Berkeley) 11/05/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 extern struct vnodeops lfs_fifoops, lfs_specops; 53 54 ump = VFSTOUFS(mntp); 55 dev = ump->um_dev; 56 if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 57 return (0); 58 59 /* Allocate new vnode/inode. */ 60 if (error = lfs_vcreate(mntp, ino, &vp)) { 61 *vpp = NULL; 62 return (error); 63 } 64 /* 65 * Put it onto its hash chain and lock it so that other requests for 66 * this inode will block if they arrive while we are sleeping waiting 67 * for old data structures to be purged or for the contents of the 68 * disk portion of this inode to be read. 69 */ 70 ip = VTOI(vp); 71 ufs_ihashins(ip); 72 73 /* Read in the disk contents for the inode, copy into the inode. */ 74 fs = ump->um_lfs; 75 if (error = bread(ump->um_devvp, lfs_itod(fs, ino), 76 (int)fs->lfs_bsize, NOCRED, &bp)) { 77 /* 78 * The inode does not contain anything useful, so it would 79 * be misleading to leave it on its hash chain. Iput() will 80 * return it to the free list. 81 */ 82 remque(ip); 83 ip->i_forw = ip; 84 ip->i_back = ip; 85 86 /* Unlock and discard unneeded inode. */ 87 ufs_iput(ip); 88 brelse(bp); 89 *vpp = NULL; 90 return (error); 91 } 92 ip->i_din = *lfs_ifind(fs, ino, bp->b_un.b_dino); 93 brelse(bp); 94 95 /* 96 * Initialize the vnode from the inode, check for aliases. In all 97 * cases re-init ip, the underlying vnode/inode may have changed. 98 */ 99 if (error = ufs_vinit(mntp, &lfs_specops, &lfs_fifoops, &vp)) { 100 ufs_iput(ip); 101 *vpp = NULL; 102 return (error); 103 } 104 /* 105 * Finish inode initialization now that aliasing has been resolved. 106 */ 107 ip = VTOI(vp); 108 ip->i_lfs = ump->um_lfs; 109 ip->i_devvp = ump->um_devvp; 110 VREF(ip->i_devvp); 111 *vpp = vp; 112 return (0); 113 } 114 115 int 116 lfs_update(vp, ta, tm, waitfor) 117 register struct vnode *vp; 118 struct timeval *ta, *tm; 119 int waitfor; 120 { 121 struct inode *ip; 122 123 if (vp->v_mount->mnt_flag & MNT_RDONLY) 124 return (0); 125 ip = VTOI(vp); 126 if ((ip->i_flag & (IUPD|IACC|ICHG|IMOD)) == 0) 127 return (0); 128 if (ip->i_flag&IACC) 129 ip->i_atime = ta->tv_sec; 130 if (ip->i_flag&IUPD) 131 ip->i_mtime = tm->tv_sec; 132 if (ip->i_flag&ICHG) 133 ip->i_ctime = time.tv_sec; 134 ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD); 135 136 /* 137 * XXX 138 * I'm not real sure what to do here; once we have fsync and partial 139 * segments working in the LFS context, this must be fixed to be 140 * correct. The contents of the inode have to be pushed back to 141 * stable storage; note that the ifile contains the access time of 142 * the inode and must be updated as well. 143 */ 144 return (0); 145 } 146 147 /* 148 * Truncate the inode ip to at most length size. 149 * 150 * NB: triple indirect blocks are untested. 151 */ 152 /* ARGSUSED */ 153 int 154 lfs_truncate(ovp, length, flags) 155 struct vnode *ovp; 156 u_long length; 157 int flags; 158 { 159 register struct lfs *fs; 160 register struct inode *oip; 161 struct buf *bp; 162 daddr_t lbn; 163 int error, offset, size; 164 165 vnode_pager_setsize(ovp, length); 166 oip = VTOI(ovp); 167 168 /* If length is larger than the file, just update the times. */ 169 if (oip->i_size <= length) { 170 oip->i_flag |= ICHG|IUPD; 171 ITIMES(oip, &time, &time); 172 return (0); 173 } 174 175 /* 176 * Update the size of the file. If the file is not being truncated to 177 * a block boundry, the contents of the partial block following the end 178 * of the file must be zero'ed in case it ever become accessable again 179 * because of subsequent file growth. 180 */ 181 fs = oip->i_lfs; 182 offset = blkoff(fs, length); 183 if (offset == 0) 184 oip->i_size = length; 185 else { 186 lbn = lblkno(fs, length); 187 #ifdef QUOTA 188 if (error = getinoquota(oip)) 189 return (error); 190 #endif 191 if (error = bread(ovp, lbn, fs->lfs_bsize, NOCRED, &bp)) 192 return (error); 193 oip->i_size = length; 194 size = blksize(fs); /* LFS */ 195 (void) vnode_pager_uncache(ovp); 196 bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset)); 197 allocbuf(bp, size); 198 lfs_bwrite(bp); 199 } 200 /* BZERO INODE BLOCK POINTERS HERE, FOR CONSISTENCY XXX */ 201 } 202