spl5 not splimp
[unix-history] / usr / src / sys / kern / subr_xxx.c
CommitLineData
2752c877 1/* subr_xxx.c 4.9 81/11/20 */
ae9e2121
BJ
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 */
20daddr_t
21bmap(ip, bn, rwflg)
22register struct inode *ip;
23daddr_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);
c0bb1685
BJ
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);
ae9e2121
BJ
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 /*
c0bb1685 87 * fetch the first indirect block
ae9e2121
BJ
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);
c0bb1685
BJ
94 /*
95 * Write synchronously so that indirect blocks
96 * never point at garbage.
97 */
98 bwrite(bp);
ae9e2121
BJ
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);
c0bb1685
BJ
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);
ae9e2121
BJ
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 */
151passc(c)
152register 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
3d14758e 169#include "ct.h"
2752c877 170#if NCT > 0
ae9e2121
BJ
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 */
ae9e2121
BJ
178cpass()
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}
2752c877 196#endif
ae9e2121
BJ
197
198/*
199 * Routine which sets a user error; placed in
200 * illegal entries in the bdevsw and cdevsw tables.
201 */
202nodev()
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 */
212nulldev()
213{
214
215}
216
217imin(a, b)
218{
219
220 return (a < b ? a : b);
221}
222
223imax(a, b)
224{
225
226 return (a > b ? a : b);
227}
228
229struct proc *
230pfind(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}