1*1204Sbill /* subr_xxx.c 3.3 10/03/80 */ 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); 48*1204Sbill if ((ip->i_mode&IFMT) == IFDIR) 49*1204Sbill /* 50*1204Sbill * Write directory blocks synchronously 51*1204Sbill * so they never appear with garbage in 52*1204Sbill * them on the disk. 53*1204Sbill */ 54*1204Sbill bwrite(bp); 55*1204Sbill else 56*1204Sbill 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 /* 87*1204Sbill * 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); 94*1204Sbill /* 95*1204Sbill * Write synchronously so that indirect blocks 96*1204Sbill * never point at garbage. 97*1204Sbill */ 98*1204Sbill 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); 122*1204Sbill if (j < 3 || (ip->i_mode&IFMT) == IFDIR) 123*1204Sbill /* 124*1204Sbill * Write synchronously so indirect blocks 125*1204Sbill * never point at garbage and blocks 126*1204Sbill * in directories never contain garbage. 127*1204Sbill */ 128*1204Sbill bwrite(nbp); 129*1204Sbill else 130*1204Sbill 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 16934Sbill /* 17034Sbill * Pick up and return the next character from the user's 17134Sbill * write call at location u_base; 17234Sbill * update u_base, u_count, and u_offset. Return -1 17334Sbill * when u_count is exhausted. u_base is in the user's 17434Sbill * address space unless u_segflg is set. 17534Sbill */ 17634Sbill /* 17734Sbill cpass() 17834Sbill { 17934Sbill register c, id; 18034Sbill 18134Sbill if(u.u_count == 0) 18234Sbill return(-1); 18334Sbill if((id = u.u_segflg) == 1) 18434Sbill c = *u.u_base; 18534Sbill else 18634Sbill if((c = id==0?fubyte(u.u_base):fuibyte(u.u_base)) < 0) { 18734Sbill u.u_error = EFAULT; 18834Sbill return(-1); 18934Sbill } 19034Sbill u.u_count--; 19134Sbill u.u_offset++; 19234Sbill u.u_base++; 19334Sbill return(c&0377); 19434Sbill } 19534Sbill */ 19634Sbill 19734Sbill /* 19834Sbill * Routine which sets a user error; placed in 19934Sbill * illegal entries in the bdevsw and cdevsw tables. 20034Sbill */ 20134Sbill nodev() 20234Sbill { 20334Sbill 20434Sbill u.u_error = ENODEV; 20534Sbill } 20634Sbill 20734Sbill /* 20834Sbill * Null routine; placed in insignificant entries 20934Sbill * in the bdevsw and cdevsw tables. 21034Sbill */ 21134Sbill nulldev() 21234Sbill { 21334Sbill 21434Sbill } 21534Sbill 21634Sbill imin(a, b) 21734Sbill { 21834Sbill 21934Sbill return (a < b ? a : b); 22034Sbill } 22134Sbill 22234Sbill imax(a, b) 22334Sbill { 22434Sbill 22534Sbill return (a > b ? a : b); 22634Sbill } 22734Sbill 22834Sbill struct proc * 22934Sbill pfind(pid) 23034Sbill int pid; 23134Sbill { 23234Sbill register struct proc *p; 23334Sbill 23434Sbill for (p = &proc[pidhash[PIDHASH(pid)]]; p != &proc[0]; p = &proc[p->p_idhash]) 23534Sbill if (p->p_pid == pid) 23634Sbill return (p); 23734Sbill return ((struct proc *)0); 23834Sbill } 239