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