1 /* subr_xxx.c 3.3 10/03/80 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/conf.h" 6 #include "../h/inode.h" 7 #include "../h/dir.h" 8 #include "../h/user.h" 9 #include "../h/buf.h" 10 #include "../h/proc.h" 11 12 /* 13 * Bmap defines the structure of file system storage 14 * by returning the physical block number on a device given the 15 * inode and the logical block number in a file. 16 * When convenient, it also leaves the physical 17 * block number of the next block of the file in rablock 18 * for use in read-ahead. 19 */ 20 daddr_t 21 bmap(ip, bn, rwflg) 22 register struct inode *ip; 23 daddr_t bn; 24 { 25 register i; 26 struct buf *bp, *nbp; 27 int j, sh; 28 daddr_t nb, *bap; 29 dev_t dev; 30 31 if(bn < 0) { 32 u.u_error = EFBIG; 33 return((daddr_t)0); 34 } 35 dev = ip->i_dev; 36 rablock = 0; 37 38 /* 39 * blocks 0..NADDR-4 are direct blocks 40 */ 41 if(bn < NADDR-3) { 42 i = bn; 43 nb = ip->i_un.i_addr[i]; 44 if(nb == 0) { 45 if(rwflg==B_READ || (bp = alloc(dev))==NULL) 46 return((daddr_t)-1); 47 nb = dbtofsb(bp->b_blkno); 48 if ((ip->i_mode&IFMT) == IFDIR) 49 /* 50 * Write directory blocks synchronously 51 * so they never appear with garbage in 52 * them on the disk. 53 */ 54 bwrite(bp); 55 else 56 bdwrite(bp); 57 ip->i_un.i_addr[i] = nb; 58 ip->i_flag |= IUPD|ICHG; 59 } 60 if(i < NADDR-4) 61 rablock = ip->i_un.i_addr[i+1]; 62 return(nb); 63 } 64 65 /* 66 * addresses NADDR-3, NADDR-2, and NADDR-1 67 * have single, double, triple indirect blocks. 68 * the first step is to determine 69 * how many levels of indirection. 70 */ 71 sh = 0; 72 nb = 1; 73 bn -= NADDR-3; 74 for(j=3; j>0; j--) { 75 sh += NSHIFT; 76 nb <<= NSHIFT; 77 if(bn < nb) 78 break; 79 bn -= nb; 80 } 81 if(j == 0) { 82 u.u_error = EFBIG; 83 return((daddr_t)0); 84 } 85 86 /* 87 * fetch the first indirect block 88 */ 89 nb = ip->i_un.i_addr[NADDR-j]; 90 if(nb == 0) { 91 if(rwflg==B_READ || (bp = alloc(dev))==NULL) 92 return((daddr_t)-1); 93 nb = dbtofsb(bp->b_blkno); 94 /* 95 * Write synchronously so that indirect blocks 96 * never point at garbage. 97 */ 98 bwrite(bp); 99 ip->i_un.i_addr[NADDR-j] = nb; 100 ip->i_flag |= IUPD|ICHG; 101 } 102 103 /* 104 * fetch through the indirect blocks 105 */ 106 for(; j<=3; j++) { 107 bp = bread(dev, nb); 108 if(bp->b_flags & B_ERROR) { 109 brelse(bp); 110 return((daddr_t)0); 111 } 112 bap = bp->b_un.b_daddr; 113 sh -= NSHIFT; 114 i = (bn>>sh) & NMASK; 115 nb = bap[i]; 116 if(nb == 0) { 117 if(rwflg==B_READ || (nbp = alloc(dev))==NULL) { 118 brelse(bp); 119 return((daddr_t)-1); 120 } 121 nb = dbtofsb(nbp->b_blkno); 122 if (j < 3 || (ip->i_mode&IFMT) == IFDIR) 123 /* 124 * Write synchronously so indirect blocks 125 * never point at garbage and blocks 126 * in directories never contain garbage. 127 */ 128 bwrite(nbp); 129 else 130 bdwrite(nbp); 131 bap[i] = nb; 132 bdwrite(bp); 133 } else 134 brelse(bp); 135 } 136 137 /* 138 * calculate read-ahead. 139 */ 140 if(i < NINDIR-1) 141 rablock = bap[i+1]; 142 return(nb); 143 } 144 145 /* 146 * Pass back c to the user at his location u_base; 147 * update u_base, u_count, and u_offset. Return -1 148 * on the last character of the user's read. 149 * u_base is in the user address space unless u_segflg is set. 150 */ 151 passc(c) 152 register c; 153 { 154 register id; 155 156 if((id = u.u_segflg) == 1) 157 *u.u_base = c; 158 else 159 if(id?suibyte(u.u_base, c):subyte(u.u_base, c) < 0) { 160 u.u_error = EFAULT; 161 return(-1); 162 } 163 u.u_count--; 164 u.u_offset++; 165 u.u_base++; 166 return(u.u_count == 0? -1: 0); 167 } 168 169 /* 170 * Pick up and return the next character from the user's 171 * write call at location u_base; 172 * update u_base, u_count, and u_offset. Return -1 173 * when u_count is exhausted. u_base is in the user's 174 * address space unless u_segflg is set. 175 */ 176 /* 177 cpass() 178 { 179 register c, id; 180 181 if(u.u_count == 0) 182 return(-1); 183 if((id = u.u_segflg) == 1) 184 c = *u.u_base; 185 else 186 if((c = id==0?fubyte(u.u_base):fuibyte(u.u_base)) < 0) { 187 u.u_error = EFAULT; 188 return(-1); 189 } 190 u.u_count--; 191 u.u_offset++; 192 u.u_base++; 193 return(c&0377); 194 } 195 */ 196 197 /* 198 * Routine which sets a user error; placed in 199 * illegal entries in the bdevsw and cdevsw tables. 200 */ 201 nodev() 202 { 203 204 u.u_error = ENODEV; 205 } 206 207 /* 208 * Null routine; placed in insignificant entries 209 * in the bdevsw and cdevsw tables. 210 */ 211 nulldev() 212 { 213 214 } 215 216 imin(a, b) 217 { 218 219 return (a < b ? a : b); 220 } 221 222 imax(a, b) 223 { 224 225 return (a > b ? a : b); 226 } 227 228 struct proc * 229 pfind(pid) 230 int pid; 231 { 232 register struct proc *p; 233 234 for (p = &proc[pidhash[PIDHASH(pid)]]; p != &proc[0]; p = &proc[p->p_idhash]) 235 if (p->p_pid == pid) 236 return (p); 237 return ((struct proc *)0); 238 } 239