date and time created 82/07/15 20:22:23 by root
[unix-history] / usr / src / sys / kern / subr_xxx.c
... / ...
CommitLineData
1/* subr_xxx.c 4.11 82/06/07 */
2
3/* merged into kernel: @(#)subr.c 2.2 4/8/82 */
4
5#include "../h/param.h"
6#include "../h/systm.h"
7#include "../h/conf.h"
8#include "../h/inode.h"
9#include "../h/dir.h"
10#include "../h/user.h"
11#include "../h/buf.h"
12#include "../h/proc.h"
13#include "../h/fs.h"
14
15/*
16 * Bmap defines the structure of file system storage
17 * by returning the physical block number on a device given the
18 * inode and the logical block number in a file.
19 * When convenient, it also leaves the physical
20 * block number of the next block of the file in rablock
21 * for use in read-ahead.
22 */
23/*VARARGS3*/
24daddr_t
25bmap(ip, bn, rwflg, size)
26 register struct inode *ip;
27 daddr_t bn;
28 int rwflg;
29 int size; /* supplied only when rwflg == B_WRITE */
30{
31 register int i;
32 int osize, nsize;
33 struct buf *bp, *nbp;
34 struct fs *fs;
35 int j, sh;
36 daddr_t nb, *bap, pref, blkpref();
37
38 if (bn < 0) {
39 u.u_error = EFBIG;
40 return ((daddr_t)0);
41 }
42 fs = ip->i_fs;
43 rablock = 0;
44 rasize = 0; /* conservative */
45
46 /*
47 * If the next write will extend the file into a new block,
48 * and the file is currently composed of a fragment
49 * this fragment has to be extended to be a full block.
50 */
51 nb = lblkno(fs, ip->i_size);
52 if (rwflg == B_WRITE && nb < NDADDR && nb < bn) {
53 osize = blksize(fs, ip, nb);
54 if (osize < fs->fs_bsize && osize > 0) {
55 bp = realloccg(ip, ip->i_db[nb],
56 nb == 0 ? 0 : ip->i_db[nb - 1] + fs->fs_frag,
57 osize, fs->fs_bsize);
58 ip->i_size = (nb + 1) * fs->fs_bsize;
59 ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
60 ip->i_flag |= IUPD|ICHG;
61 bdwrite(bp);
62 }
63 }
64 /*
65 * The first NDADDR blocks are direct blocks
66 */
67 if (bn < NDADDR) {
68 i = bn;
69 nb = ip->i_db[i];
70 if (rwflg == B_READ) {
71 if (nb == 0)
72 return ((daddr_t)-1);
73 goto gotit;
74 }
75 if (nb == 0 || ip->i_size < (i + 1) * fs->fs_bsize) {
76 if (nb != 0) {
77 /* consider need to reallocate a frag */
78 osize = fragroundup(fs, blkoff(fs, ip->i_size));
79 nsize = fragroundup(fs, size);
80 if (nsize <= osize)
81 goto gotit;
82 bp = realloccg(ip, nb, i == 0 ?
83 0 : ip->i_db[i - 1] + fs->fs_frag,
84 osize, nsize);
85 } else {
86 if (ip->i_size < (i + 1) * fs->fs_bsize)
87 nsize = fragroundup(fs, size);
88 else
89 nsize = fs->fs_bsize;
90 bp = alloc(ip, i > 0 ?
91 ip->i_db[i - 1] + fs->fs_frag : 0,
92 nsize);
93 }
94 if (bp == NULL)
95 return ((daddr_t)-1);
96 nb = dbtofsb(fs, bp->b_blkno);
97 if ((ip->i_mode&IFMT) == IFDIR)
98 /*
99 * Write directory blocks synchronously
100 * so they never appear with garbage in
101 * them on the disk.
102 */
103 bwrite(bp);
104 else
105 bdwrite(bp);
106 ip->i_db[i] = nb;
107 ip->i_flag |= IUPD|ICHG;
108 }
109gotit:
110 if (i < NDADDR - 1) {
111 rablock = fsbtodb(fs, ip->i_db[i+1]);
112 rasize = blksize(fs, ip, i+1);
113 }
114 return (nb);
115 }
116
117 /*
118 * Determine how many levels of indirection.
119 */
120 sh = 1;
121 bn -= NDADDR;
122 for (j = NIADDR; j>0; j--) {
123 sh *= NINDIR(fs);
124 if (bn < sh)
125 break;
126 bn -= sh;
127 }
128 if (j == 0) {
129 u.u_error = EFBIG;
130 return ((daddr_t)0);
131 }
132
133 /*
134 * fetch the first indirect block
135 */
136 nb = ip->i_ib[NIADDR - j];
137 if (nb == 0) {
138 if (rwflg==B_READ ||
139 (bp = alloc(ip, (daddr_t)0, fs->fs_bsize)) == NULL)
140 return ((daddr_t)-1);
141 nb = dbtofsb(fs, bp->b_blkno);
142 /*
143 * Write synchronously so that indirect blocks
144 * never point at garbage.
145 */
146 bwrite(bp);
147 ip->i_ib[NIADDR - j] = nb;
148 ip->i_flag |= IUPD|ICHG;
149 }
150
151 /*
152 * fetch through the indirect blocks
153 */
154 for (; j <= NIADDR; j++) {
155 bp = bread(ip->i_dev, fsbtodb(fs, nb), fs->fs_bsize);
156 if (bp->b_flags & B_ERROR) {
157 brelse(bp);
158 return ((daddr_t)0);
159 }
160 bap = bp->b_un.b_daddr;
161 sh /= NINDIR(fs);
162 i = (bn / sh) % NINDIR(fs);
163 nb = bap[i];
164 if (nb == 0) {
165 if (rwflg==B_READ) {
166 brelse(bp);
167 return ((daddr_t)-1);
168 }
169 if (i % (fs->fs_fsize / sizeof(daddr_t)) == 0 ||
170 bap[i - 1] == 0)
171 pref = blkpref(ip->i_fs);
172 else
173 pref = bap[i - 1] + fs->fs_frag;
174 nbp = alloc(ip, pref, fs->fs_bsize);
175 if (nbp == NULL) {
176 brelse(bp);
177 return ((daddr_t)-1);
178 }
179 nb = dbtofsb(fs, nbp->b_blkno);
180 if (j < NIADDR || (ip->i_mode&IFMT) == IFDIR)
181 /*
182 * Write synchronously so indirect blocks
183 * never point at garbage and blocks
184 * in directories never contain garbage.
185 */
186 bwrite(nbp);
187 else
188 bdwrite(nbp);
189 bap[i] = nb;
190 bdwrite(bp);
191 } else
192 brelse(bp);
193 }
194
195 /*
196 * calculate read-ahead.
197 */
198 if (i < NINDIR(fs) - 1) {
199 rablock = fsbtodb(fs, bap[i+1]);
200 rasize = fs->fs_bsize;
201 }
202 return (nb);
203}
204
205/*
206 * Pass back c to the user at his location u_base;
207 * update u_base, u_count, and u_offset. Return -1
208 * on the last character of the user's read.
209 * u_base is in the user address space unless u_segflg is set.
210 */
211passc(c)
212register c;
213{
214 register id;
215
216 if ((id = u.u_segflg) == 1)
217 *u.u_base = c;
218 else
219 if (id?suibyte(u.u_base, c):subyte(u.u_base, c) < 0) {
220 u.u_error = EFAULT;
221 return (-1);
222 }
223 u.u_count--;
224 u.u_offset++;
225 u.u_base++;
226 return (u.u_count == 0? -1: 0);
227}
228
229#include "ct.h"
230#if NCT > 0
231/*
232 * Pick up and return the next character from the user's
233 * write call at location u_base;
234 * update u_base, u_count, and u_offset. Return -1
235 * when u_count is exhausted. u_base is in the user's
236 * address space unless u_segflg is set.
237 */
238cpass()
239{
240 register c, id;
241
242 if (u.u_count == 0)
243 return (-1);
244 if ((id = u.u_segflg) == 1)
245 c = *u.u_base;
246 else
247 if ((c = id==0?fubyte(u.u_base):fuibyte(u.u_base)) < 0) {
248 u.u_error = EFAULT;
249 return (-1);
250 }
251 u.u_count--;
252 u.u_offset++;
253 u.u_base++;
254 return (c&0377);
255}
256#endif
257
258/*
259 * Routine which sets a user error; placed in
260 * illegal entries in the bdevsw and cdevsw tables.
261 */
262nodev()
263{
264
265 u.u_error = ENODEV;
266}
267
268/*
269 * Null routine; placed in insignificant entries
270 * in the bdevsw and cdevsw tables.
271 */
272nulldev()
273{
274
275}
276
277imin(a, b)
278{
279
280 return (a < b ? a : b);
281}
282
283imax(a, b)
284{
285
286 return (a > b ? a : b);
287}
288
289unsigned
290min(a, b)
291 unsigned int a, b;
292{
293
294 return (a < b ? a : b);
295}
296
297unsigned
298max(a, b)
299 unsigned int a, b;
300{
301
302 return (a > b ? a : b);
303}
304
305struct proc *
306pfind(pid)
307 int pid;
308{
309 register struct proc *p;
310
311 for (p = &proc[pidhash[PIDHASH(pid)]]; p != &proc[0]; p = &proc[p->p_idhash])
312 if (p->p_pid == pid)
313 return (p);
314 return ((struct proc *)0);
315}