xref: /original-bsd/sys/kern/subr_xxx.c (revision 6c57d260)
1 /*	subr_xxx.c	4.7	81/03/11	*/
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/conf.h"
6 #include "../h/inode.h"
7 #include "../h/dir.h"
8 #include "../h/user.h"
9 #include "../h/buf.h"
10 #include "../h/proc.h"
11 
12 /*
13  * Bmap defines the structure of file system storage
14  * by returning the physical block number on a device given the
15  * inode and the logical block number in a file.
16  * When convenient, it also leaves the physical
17  * block number of the next block of the file in rablock
18  * for use in read-ahead.
19  */
20 daddr_t
21 bmap(ip, bn, rwflg)
22 register struct inode *ip;
23 daddr_t bn;
24 {
25 	register i;
26 	struct buf *bp, *nbp;
27 	int j, sh;
28 	daddr_t nb, *bap;
29 	dev_t dev;
30 
31 	if(bn < 0) {
32 		u.u_error = EFBIG;
33 		return((daddr_t)0);
34 	}
35 	dev = ip->i_dev;
36 	rablock = 0;
37 
38 	/*
39 	 * blocks 0..NADDR-4 are direct blocks
40 	 */
41 	if(bn < NADDR-3) {
42 		i = bn;
43 		nb = ip->i_un.i_addr[i];
44 		if(nb == 0) {
45 			if(rwflg==B_READ || (bp = alloc(dev))==NULL)
46 				return((daddr_t)-1);
47 			nb = dbtofsb(bp->b_blkno);
48 			if ((ip->i_mode&IFMT) == IFDIR)
49 				/*
50 				 * Write directory blocks synchronously
51 				 * so they never appear with garbage in
52 				 * them on the disk.
53 				 */
54 				bwrite(bp);
55 			else
56 				bdwrite(bp);
57 			ip->i_un.i_addr[i] = nb;
58 			ip->i_flag |= IUPD|ICHG;
59 		}
60 		if(i < NADDR-4)
61 			rablock = ip->i_un.i_addr[i+1];
62 		return(nb);
63 	}
64 
65 	/*
66 	 * addresses NADDR-3, NADDR-2, and NADDR-1
67 	 * have single, double, triple indirect blocks.
68 	 * the first step is to determine
69 	 * how many levels of indirection.
70 	 */
71 	sh = 0;
72 	nb = 1;
73 	bn -= NADDR-3;
74 	for(j=3; j>0; j--) {
75 		sh += NSHIFT;
76 		nb <<= NSHIFT;
77 		if(bn < nb)
78 			break;
79 		bn -= nb;
80 	}
81 	if(j == 0) {
82 		u.u_error = EFBIG;
83 		return((daddr_t)0);
84 	}
85 
86 	/*
87 	 * fetch the first indirect block
88 	 */
89 	nb = ip->i_un.i_addr[NADDR-j];
90 	if(nb == 0) {
91 		if(rwflg==B_READ || (bp = alloc(dev))==NULL)
92 			return((daddr_t)-1);
93 		nb = dbtofsb(bp->b_blkno);
94 		/*
95 		 * Write synchronously so that indirect blocks
96 		 * never point at garbage.
97 		 */
98 		bwrite(bp);
99 		ip->i_un.i_addr[NADDR-j] = nb;
100 		ip->i_flag |= IUPD|ICHG;
101 	}
102 
103 	/*
104 	 * fetch through the indirect blocks
105 	 */
106 	for(; j<=3; j++) {
107 		bp = bread(dev, nb);
108 		if(bp->b_flags & B_ERROR) {
109 			brelse(bp);
110 			return((daddr_t)0);
111 		}
112 		bap = bp->b_un.b_daddr;
113 		sh -= NSHIFT;
114 		i = (bn>>sh) & NMASK;
115 		nb = bap[i];
116 		if(nb == 0) {
117 			if(rwflg==B_READ || (nbp = alloc(dev))==NULL) {
118 				brelse(bp);
119 				return((daddr_t)-1);
120 			}
121 			nb = dbtofsb(nbp->b_blkno);
122 			if (j < 3 || (ip->i_mode&IFMT) == IFDIR)
123 				/*
124 				 * Write synchronously so indirect blocks
125 				 * never point at garbage and blocks
126 				 * in directories never contain garbage.
127 				 */
128 				bwrite(nbp);
129 			else
130 				bdwrite(nbp);
131 			bap[i] = nb;
132 			bdwrite(bp);
133 		} else
134 			brelse(bp);
135 	}
136 
137 	/*
138 	 * calculate read-ahead.
139 	 */
140 	if(i < NINDIR-1)
141 		rablock = bap[i+1];
142 	return(nb);
143 }
144 
145 /*
146  * Pass back  c  to the user at his location u_base;
147  * update u_base, u_count, and u_offset.  Return -1
148  * on the last character of the user's read.
149  * u_base is in the user address space unless u_segflg is set.
150  */
151 passc(c)
152 register c;
153 {
154 	register id;
155 
156 	if((id = u.u_segflg) == 1)
157 		*u.u_base = c;
158 	else
159 		if(id?suibyte(u.u_base, c):subyte(u.u_base, c) < 0) {
160 			u.u_error = EFAULT;
161 			return(-1);
162 		}
163 	u.u_count--;
164 	u.u_offset++;
165 	u.u_base++;
166 	return(u.u_count == 0? -1: 0);
167 }
168 
169 #include "ct.h"
170 #if NCT > 0
171 /*
172  * Pick up and return the next character from the user's
173  * write call at location u_base;
174  * update u_base, u_count, and u_offset.  Return -1
175  * when u_count is exhausted.  u_base is in the user's
176  * address space unless u_segflg is set.
177  */
178 cpass()
179 {
180 	register c, id;
181 
182 	if(u.u_count == 0)
183 		return(-1);
184 	if((id = u.u_segflg) == 1)
185 		c = *u.u_base;
186 	else
187 		if((c = id==0?fubyte(u.u_base):fuibyte(u.u_base)) < 0) {
188 			u.u_error = EFAULT;
189 			return(-1);
190 		}
191 	u.u_count--;
192 	u.u_offset++;
193 	u.u_base++;
194 	return(c&0377);
195 }
196 #endif
197 
198 /*
199  * Routine which sets a user error; placed in
200  * illegal entries in the bdevsw and cdevsw tables.
201  */
202 nodev()
203 {
204 
205 	u.u_error = ENODEV;
206 }
207 
208 /*
209  * Null routine; placed in insignificant entries
210  * in the bdevsw and cdevsw tables.
211  */
212 nulldev()
213 {
214 
215 }
216 
217 imin(a, b)
218 {
219 
220 	return (a < b ? a : b);
221 }
222 
223 imax(a, b)
224 {
225 
226 	return (a > b ? a : b);
227 }
228 
229 struct proc *
230 pfind(pid)
231 	int pid;
232 {
233 	register struct proc *p;
234 
235 	for (p = &proc[pidhash[PIDHASH(pid)]]; p != &proc[0]; p = &proc[p->p_idhash])
236 		if (p->p_pid == pid)
237 			return (p);
238 	return ((struct proc *)0);
239 }
240