|
|
1.1 root 1: #include "sys/param.h"
2: #include "sys/systm.h"
3: #include "sys/inode.h"
4: #include "sys/user.h"
5: #include "sys/buf.h"
6: #include "sys/proc.h"
7:
8: /*
9: * Bmap defines the structure of file system storage
10: * by returning the physical block number on a device given the
11: * inode and the logical block number in a file.
12: * When convenient, it also leaves the physical
13: * block number of the next block of the file in rablock
14: * for use in read-ahead.
15: */
16: daddr_t
17: bmap(ip, bn, rwflg)
18: register struct inode *ip;
19: daddr_t bn;
20: {
21: register daddr_t i;
22: struct buf *bp, *nbp;
23: int j, sh;
24: daddr_t prev;
25: daddr_t nb, *bap;
26: dev_t dev;
27:
28: if(bn < 0) {
29: u.u_error = EFBIG;
30: return((daddr_t)0);
31: }
32: dev = ip->i_dev;
33: rablock = 0;
34:
35: /*
36: * blocks 0..NADDR-4 are direct blocks
37: */
38: if(bn < NADDR-3) {
39: i = bn;
40: nb = ip->i_un.i_addr[i];
41: if(nb == 0) {
42: prev = (i > 0? ip->i_un.i_addr[i-1]: 0);
43: if(rwflg==B_READ || (bp = alloc(ip, prev))==NULL)
44: return((daddr_t)-1);
45: nb = dbtofsb(dev, bp->b_blkno);
46: if ((ip->i_mode&IFMT) == IFDIR)
47: /*
48: * Write directory blocks synchronously
49: * so they never appear with garbage in
50: * them on the disk.
51: */
52: bwrite(bp);
53: else
54: bdwrite(bp);
55: ip->i_un.i_addr[i] = nb;
56: ip->i_flag |= IUPD|ICHG;
57: }
58: if(i < NADDR-4)
59: rablock = ip->i_un.i_addr[i+1];
60: return(nb);
61: }
62:
63: /*
64: * addresses NADDR-3, NADDR-2, and NADDR-1
65: * have single, double, triple indirect blocks.
66: * the first step is to determine
67: * how many levels of indirection.
68: */
69: sh = 0;
70: nb = 1;
71: bn -= NADDR-3;
72: for(j=3; j>0; j--) {
73: sh += NSHIFT(dev);
74: nb <<= NSHIFT(dev);
75: if(bn < nb)
76: break;
77: bn -= nb;
78: }
79: if(j == 0) {
80: u.u_error = EFBIG;
81: return((daddr_t)0);
82: }
83:
84: /*
85: * fetch the first indirect block
86: */
87: nb = ip->i_un.i_addr[NADDR-j];
88: if(nb == 0) {
89: prev = ip->i_un.i_addr[NADDR-j-1];
90: if(rwflg==B_READ || (bp = alloc(ip, prev))==NULL)
91: return((daddr_t)-1);
92: nb = dbtofsb(dev, bp->b_blkno);
93: /*
94: * Write synchronously so that indirect blocks
95: * never point at garbage.
96: */
97: bwrite(bp);
98: ip->i_un.i_addr[NADDR-j] = nb;
99: ip->i_flag |= IUPD|ICHG;
100: }
101:
102: /*
103: * fetch through the indirect blocks
104: */
105: for(; j<=3; j++) {
106: bp = bread(dev, nb);
107: if(bp->b_flags & B_ERROR) {
108: brelse(bp);
109: return((daddr_t)0);
110: }
111: bap = bp->b_un.b_daddr;
112: sh -= NSHIFT(dev);
113: i = (bn>>sh) & NMASK(dev);
114: nb = bap[i];
115: if(nb == 0) {
116: prev = (i>0? bap[i-1]: 0);
117: if(rwflg==B_READ || (nbp = alloc(ip, prev))==NULL) {
118: brelse(bp);
119: return((daddr_t)-1);
120: }
121: nb = dbtofsb(dev, 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(dev)-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) == SEGSYS)
157: *u.u_base = c;
158: else
159: if(id==SEGUINST?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 = Lladd(u.u_offset, 1);
165: u.u_base++;
166: return(u.u_count == 0? -1: 0);
167: }
168:
169: /*
170: * Pick up and return the next character from the user's
171: * write call at location u_base;
172: * update u_base, u_count, and u_offset. Return -1
173: * when u_count is exhausted. u_base is in the user's
174: * address space unless u_segflg is set.
175: */
176: cpass()
177: {
178: register c, id;
179:
180: if(u.u_count == 0)
181: return(-1);
182: if((id = u.u_segflg) == SEGSYS)
183: c = *u.u_base;
184: else
185: if((c = id==SEGUDATA?fubyte(u.u_base):fuibyte(u.u_base)) < 0) {
186: u.u_error = EFAULT;
187: return(-1);
188: }
189: u.u_count--;
190: u.u_offset = Lladd(u.u_offset, 1);
191: u.u_base++;
192: return(c&0377);
193: }
194:
195: /*
196: * Routine which sets a user error; placed in
197: * illegal entries in the bdevsw and cdevsw tables.
198: */
199: nodev()
200: {
201:
202: u.u_error = ENODEV;
203: }
204:
205: /*
206: * Null routine; placed in insignificant entries
207: * in the bdevsw and cdevsw tables.
208: */
209: nulldev()
210: {
211:
212: }
213:
214: imin(a, b)
215: {
216:
217: return (a < b ? a : b);
218: }
219:
220: imax(a, b)
221: {
222:
223: return (a > b ? a : b);
224: }
225:
226: /*
227: * this should probably come out eventually
228: */
229: struct proc *
230: pfind(pid)
231: register int pid;
232: {
233: register struct proc *p;
234:
235: for (p = proc; p < procNPROC; p++)
236: if (p->p_stat && p->p_pid == pid)
237: return (p);
238: return (NULL);
239: }
240:
241: strncmp(s1, s2, len)
242: register char *s1, *s2;
243: register len;
244: {
245: do {
246: if (*s1 != *s2++)
247: return(1);
248: if (*s1++ == '\0')
249: return(0);
250: } while (--len);
251: return(0);
252: }
253:
254: strcpy(to, fr)
255: register char *to, *fr;
256: {
257: while (*to++ = *fr++)
258: ;
259: }
260:
261: /*
262: * long-long support
263: */
264:
265: #define M 0x80000000
266:
267: unsigned
268: Lshift(ll, l)
269: llong_t ll;
270: long l;
271: {
272: return (ll.hi<<(32-l)) | (ll.lo>>l);
273: }
274:
275: llong_t
276: ltoL(l)
277: long l;
278: {
279: llong_t t;
280:
281: t.hi = 0;
282: t.lo = l;
283: return t;
284: }
285:
286: llong_t
287: Lladd(ll, l)
288: llong_t ll;
289: long l;
290: {
291: llong_t t;
292: long cin;
293:
294: t = ll;
295: t.lo += l;
296: cin = ll.lo^t.lo;
297: if (l>=0) {
298: if ((ll.lo&cin)&M)
299: t.hi++;
300: } else {
301: if ((~ll.lo&cin)&M)
302: t.hi--;
303: }
304: return t;
305: }
306:
307: llong_t
308: Luadd(ll, u)
309: llong_t ll;
310: unsigned long u;
311: {
312: llong_t t;
313: long cin;
314:
315: t = ll;
316: t.lo += u;
317: cin = ll.lo^t.lo;
318: if ((ll.lo&cin)&M)
319: t.hi++;
320: return t;
321: }
322:
323: llong_t
324: LLadd(lla, llb)
325: llong_t lla, llb;
326: {
327: llong_t t;
328:
329: t.hi = lla.hi+llb.hi;
330: t.lo = lla.lo+llb.lo;
331: if ((lla.lo&llb.lo | lla.lo&~t.lo | llb.lo&~t.lo)&M)
332: t.hi++;
333: return t;
334: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.