xref: /csrg-svn/sys/kern/subr_xxx.c (revision 3216)
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