date and time created 82/07/15 20:22:23 by root
[unix-history] / usr / src / sys / kern / subr_xxx.c
CommitLineData
84baaab3 1/* subr_xxx.c 4.11 82/06/07 */
6459ebe0
KM
2
3/* merged into kernel: @(#)subr.c 2.2 4/8/82 */
ae9e2121
BJ
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"
6459ebe0 13#include "../h/fs.h"
ae9e2121
BJ
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 */
6459ebe0 23/*VARARGS3*/
ae9e2121 24daddr_t
6459ebe0
KM
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 */
ae9e2121 30{
6459ebe0
KM
31 register int i;
32 int osize, nsize;
ae9e2121 33 struct buf *bp, *nbp;
6459ebe0 34 struct fs *fs;
ae9e2121 35 int j, sh;
6459ebe0 36 daddr_t nb, *bap, pref, blkpref();
ae9e2121 37
6459ebe0 38 if (bn < 0) {
ae9e2121 39 u.u_error = EFBIG;
6459ebe0 40 return ((daddr_t)0);
ae9e2121 41 }
6459ebe0 42 fs = ip->i_fs;
ae9e2121 43 rablock = 0;
84baaab3 44 rasize = 0; /* conservative */
ae9e2121
BJ
45
46 /*
6459ebe0
KM
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.
ae9e2121 50 */
6459ebe0
KM
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) {
ae9e2121 68 i = bn;
6459ebe0
KM
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);
c0bb1685
BJ
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);
6459ebe0 106 ip->i_db[i] = nb;
ae9e2121
BJ
107 ip->i_flag |= IUPD|ICHG;
108 }
6459ebe0 109gotit:
84baaab3
KM
110 if (i < NDADDR - 1) {
111 rablock = fsbtodb(fs, ip->i_db[i+1]);
112 rasize = blksize(fs, ip, i+1);
113 }
6459ebe0 114 return (nb);
ae9e2121
BJ
115 }
116
117 /*
6459ebe0 118 * Determine how many levels of indirection.
ae9e2121 119 */
6459ebe0
KM
120 sh = 1;
121 bn -= NDADDR;
122 for (j = NIADDR; j>0; j--) {
123 sh *= NINDIR(fs);
124 if (bn < sh)
ae9e2121 125 break;
6459ebe0 126 bn -= sh;
ae9e2121 127 }
6459ebe0 128 if (j == 0) {
ae9e2121 129 u.u_error = EFBIG;
6459ebe0 130 return ((daddr_t)0);
ae9e2121
BJ
131 }
132
133 /*
c0bb1685 134 * fetch the first indirect block
ae9e2121 135 */
6459ebe0
KM
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);
c0bb1685
BJ
142 /*
143 * Write synchronously so that indirect blocks
144 * never point at garbage.
145 */
146 bwrite(bp);
6459ebe0 147 ip->i_ib[NIADDR - j] = nb;
ae9e2121
BJ
148 ip->i_flag |= IUPD|ICHG;
149 }
150
151 /*
152 * fetch through the indirect blocks
153 */
6459ebe0
KM
154 for (; j <= NIADDR; j++) {
155 bp = bread(ip->i_dev, fsbtodb(fs, nb), fs->fs_bsize);
156 if (bp->b_flags & B_ERROR) {
ae9e2121 157 brelse(bp);
6459ebe0 158 return ((daddr_t)0);
ae9e2121
BJ
159 }
160 bap = bp->b_un.b_daddr;
6459ebe0
KM
161 sh /= NINDIR(fs);
162 i = (bn / sh) % NINDIR(fs);
ae9e2121 163 nb = bap[i];
6459ebe0
KM
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) {
ae9e2121 176 brelse(bp);
6459ebe0 177 return ((daddr_t)-1);
ae9e2121 178 }
6459ebe0
KM
179 nb = dbtofsb(fs, nbp->b_blkno);
180 if (j < NIADDR || (ip->i_mode&IFMT) == IFDIR)
c0bb1685
BJ
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);
ae9e2121
BJ
189 bap[i] = nb;
190 bdwrite(bp);
191 } else
192 brelse(bp);
193 }
194
195 /*
196 * calculate read-ahead.
197 */
84baaab3
KM
198 if (i < NINDIR(fs) - 1) {
199 rablock = fsbtodb(fs, bap[i+1]);
200 rasize = fs->fs_bsize;
201 }
6459ebe0 202 return (nb);
ae9e2121
BJ
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
6459ebe0 216 if ((id = u.u_segflg) == 1)
ae9e2121
BJ
217 *u.u_base = c;
218 else
6459ebe0 219 if (id?suibyte(u.u_base, c):subyte(u.u_base, c) < 0) {
ae9e2121 220 u.u_error = EFAULT;
6459ebe0 221 return (-1);
ae9e2121
BJ
222 }
223 u.u_count--;
224 u.u_offset++;
225 u.u_base++;
6459ebe0 226 return (u.u_count == 0? -1: 0);
ae9e2121
BJ
227}
228
3d14758e 229#include "ct.h"
2752c877 230#if NCT > 0
ae9e2121
BJ
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 */
ae9e2121
BJ
238cpass()
239{
240 register c, id;
241
6459ebe0
KM
242 if (u.u_count == 0)
243 return (-1);
244 if ((id = u.u_segflg) == 1)
ae9e2121
BJ
245 c = *u.u_base;
246 else
6459ebe0 247 if ((c = id==0?fubyte(u.u_base):fuibyte(u.u_base)) < 0) {
ae9e2121 248 u.u_error = EFAULT;
6459ebe0 249 return (-1);
ae9e2121
BJ
250 }
251 u.u_count--;
252 u.u_offset++;
253 u.u_base++;
6459ebe0 254 return (c&0377);
ae9e2121 255}
2752c877 256#endif
ae9e2121
BJ
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
6459ebe0
KM
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
ae9e2121
BJ
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}