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