1*3216Swnj /* subr_xxx.c 4.6 81/03/11 */ 234Sbill 334Sbill #include "../h/param.h" 434Sbill #include "../h/systm.h" 534Sbill #include "../h/conf.h" 634Sbill #include "../h/inode.h" 734Sbill #include "../h/dir.h" 834Sbill #include "../h/user.h" 934Sbill #include "../h/buf.h" 1034Sbill #include "../h/proc.h" 1134Sbill 1234Sbill /* 1334Sbill * Bmap defines the structure of file system storage 1434Sbill * by returning the physical block number on a device given the 1534Sbill * inode and the logical block number in a file. 1634Sbill * When convenient, it also leaves the physical 1734Sbill * block number of the next block of the file in rablock 1834Sbill * for use in read-ahead. 1934Sbill */ 2034Sbill daddr_t 2134Sbill bmap(ip, bn, rwflg) 2234Sbill register struct inode *ip; 2334Sbill daddr_t bn; 2434Sbill { 2534Sbill register i; 2634Sbill struct buf *bp, *nbp; 2734Sbill int j, sh; 2834Sbill daddr_t nb, *bap; 2934Sbill dev_t dev; 3034Sbill 3134Sbill if(bn < 0) { 3234Sbill u.u_error = EFBIG; 3334Sbill return((daddr_t)0); 3434Sbill } 3534Sbill dev = ip->i_dev; 3634Sbill rablock = 0; 3734Sbill 3834Sbill /* 3934Sbill * blocks 0..NADDR-4 are direct blocks 4034Sbill */ 4134Sbill if(bn < NADDR-3) { 4234Sbill i = bn; 4334Sbill nb = ip->i_un.i_addr[i]; 4434Sbill if(nb == 0) { 4534Sbill if(rwflg==B_READ || (bp = alloc(dev))==NULL) 4634Sbill return((daddr_t)-1); 4734Sbill nb = dbtofsb(bp->b_blkno); 481204Sbill if ((ip->i_mode&IFMT) == IFDIR) 491204Sbill /* 501204Sbill * Write directory blocks synchronously 511204Sbill * so they never appear with garbage in 521204Sbill * them on the disk. 531204Sbill */ 541204Sbill bwrite(bp); 551204Sbill else 561204Sbill bdwrite(bp); 5734Sbill ip->i_un.i_addr[i] = nb; 5834Sbill ip->i_flag |= IUPD|ICHG; 5934Sbill } 6034Sbill if(i < NADDR-4) 6134Sbill rablock = ip->i_un.i_addr[i+1]; 6234Sbill return(nb); 6334Sbill } 6434Sbill 6534Sbill /* 6634Sbill * addresses NADDR-3, NADDR-2, and NADDR-1 6734Sbill * have single, double, triple indirect blocks. 6834Sbill * the first step is to determine 6934Sbill * how many levels of indirection. 7034Sbill */ 7134Sbill sh = 0; 7234Sbill nb = 1; 7334Sbill bn -= NADDR-3; 7434Sbill for(j=3; j>0; j--) { 7534Sbill sh += NSHIFT; 7634Sbill nb <<= NSHIFT; 7734Sbill if(bn < nb) 7834Sbill break; 7934Sbill bn -= nb; 8034Sbill } 8134Sbill if(j == 0) { 8234Sbill u.u_error = EFBIG; 8334Sbill return((daddr_t)0); 8434Sbill } 8534Sbill 8634Sbill /* 871204Sbill * fetch the first indirect block 8834Sbill */ 8934Sbill nb = ip->i_un.i_addr[NADDR-j]; 9034Sbill if(nb == 0) { 9134Sbill if(rwflg==B_READ || (bp = alloc(dev))==NULL) 9234Sbill return((daddr_t)-1); 9334Sbill nb = dbtofsb(bp->b_blkno); 941204Sbill /* 951204Sbill * Write synchronously so that indirect blocks 961204Sbill * never point at garbage. 971204Sbill */ 981204Sbill bwrite(bp); 9934Sbill ip->i_un.i_addr[NADDR-j] = nb; 10034Sbill ip->i_flag |= IUPD|ICHG; 10134Sbill } 10234Sbill 10334Sbill /* 10434Sbill * fetch through the indirect blocks 10534Sbill */ 10634Sbill for(; j<=3; j++) { 10734Sbill bp = bread(dev, nb); 10834Sbill if(bp->b_flags & B_ERROR) { 10934Sbill brelse(bp); 11034Sbill return((daddr_t)0); 11134Sbill } 11234Sbill bap = bp->b_un.b_daddr; 11334Sbill sh -= NSHIFT; 11434Sbill i = (bn>>sh) & NMASK; 11534Sbill nb = bap[i]; 11634Sbill if(nb == 0) { 11734Sbill if(rwflg==B_READ || (nbp = alloc(dev))==NULL) { 11834Sbill brelse(bp); 11934Sbill return((daddr_t)-1); 12034Sbill } 12134Sbill nb = dbtofsb(nbp->b_blkno); 1221204Sbill if (j < 3 || (ip->i_mode&IFMT) == IFDIR) 1231204Sbill /* 1241204Sbill * Write synchronously so indirect blocks 1251204Sbill * never point at garbage and blocks 1261204Sbill * in directories never contain garbage. 1271204Sbill */ 1281204Sbill bwrite(nbp); 1291204Sbill else 1301204Sbill bdwrite(nbp); 13134Sbill bap[i] = nb; 13234Sbill bdwrite(bp); 13334Sbill } else 13434Sbill brelse(bp); 13534Sbill } 13634Sbill 13734Sbill /* 13834Sbill * calculate read-ahead. 13934Sbill */ 14034Sbill if(i < NINDIR-1) 14134Sbill rablock = bap[i+1]; 14234Sbill return(nb); 14334Sbill } 14434Sbill 14534Sbill /* 14634Sbill * Pass back c to the user at his location u_base; 14734Sbill * update u_base, u_count, and u_offset. Return -1 14834Sbill * on the last character of the user's read. 14934Sbill * u_base is in the user address space unless u_segflg is set. 15034Sbill */ 15134Sbill passc(c) 15234Sbill register c; 15334Sbill { 15434Sbill register id; 15534Sbill 15634Sbill if((id = u.u_segflg) == 1) 15734Sbill *u.u_base = c; 15834Sbill else 15934Sbill if(id?suibyte(u.u_base, c):subyte(u.u_base, c) < 0) { 16034Sbill u.u_error = EFAULT; 16134Sbill return(-1); 16234Sbill } 16334Sbill u.u_count--; 16434Sbill u.u_offset++; 16534Sbill u.u_base++; 16634Sbill return(u.u_count == 0? -1: 0); 16734Sbill } 16834Sbill 169*3216Swnj #include "ct." 170*3216Swnj #if NCT > 0 17134Sbill /* 17234Sbill * Pick up and return the next character from the user's 17334Sbill * write call at location u_base; 17434Sbill * update u_base, u_count, and u_offset. Return -1 17534Sbill * when u_count is exhausted. u_base is in the user's 17634Sbill * address space unless u_segflg is set. 17734Sbill */ 17834Sbill cpass() 17934Sbill { 18034Sbill register c, id; 18134Sbill 18234Sbill if(u.u_count == 0) 18334Sbill return(-1); 18434Sbill if((id = u.u_segflg) == 1) 18534Sbill c = *u.u_base; 18634Sbill else 18734Sbill if((c = id==0?fubyte(u.u_base):fuibyte(u.u_base)) < 0) { 18834Sbill u.u_error = EFAULT; 18934Sbill return(-1); 19034Sbill } 19134Sbill u.u_count--; 19234Sbill u.u_offset++; 19334Sbill u.u_base++; 19434Sbill return(c&0377); 19534Sbill } 1963102Swnj #endif 19734Sbill 19834Sbill /* 19934Sbill * Routine which sets a user error; placed in 20034Sbill * illegal entries in the bdevsw and cdevsw tables. 20134Sbill */ 20234Sbill nodev() 20334Sbill { 20434Sbill 20534Sbill u.u_error = ENODEV; 20634Sbill } 20734Sbill 20834Sbill /* 20934Sbill * Null routine; placed in insignificant entries 21034Sbill * in the bdevsw and cdevsw tables. 21134Sbill */ 21234Sbill nulldev() 21334Sbill { 21434Sbill 21534Sbill } 21634Sbill 21734Sbill imin(a, b) 21834Sbill { 21934Sbill 22034Sbill return (a < b ? a : b); 22134Sbill } 22234Sbill 22334Sbill imax(a, b) 22434Sbill { 22534Sbill 22634Sbill return (a > b ? a : b); 22734Sbill } 22834Sbill 22934Sbill struct proc * 23034Sbill pfind(pid) 23134Sbill int pid; 23234Sbill { 23334Sbill register struct proc *p; 23434Sbill 23534Sbill for (p = &proc[pidhash[PIDHASH(pid)]]; p != &proc[0]; p = &proc[p->p_idhash]) 23634Sbill if (p->p_pid == pid) 23734Sbill return (p); 23834Sbill return ((struct proc *)0); 23934Sbill } 240