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