|
|
1.1 root 1: /* $Header: /kernel/kersrc/coh.286/RCS/fs3.c,v 1.1 92/07/17 15:18:08 bin Exp Locker: bin $ */
2: /* (lgl-
3: * The information contained herein is a trade secret of Mark Williams
4: * Company, and is confidential information. It is provided under a
5: * license agreement, and may be copied or disclosed only under the
6: * terms of that agreement. Any reproduction or disclosure of this
7: * material without the express written authorization of Mark Williams
8: * Company or persuant to the license agreement is unlawful.
9: *
10: * COHERENT Version 2.3.37
11: * Copyright (c) 1982, 1983, 1984.
12: * An unpublished work by Mark Williams Company, Chicago.
13: * All rights reserved.
14: -lgl) */
15: /*
16: * Coherent.
17: * Filesystem (I/O).
18: *
19: * $Log: fs3.c,v $
20: * Revision 1.1 92/07/17 15:18:08 bin
21: * Initial revision
22: *
23: * Revision 1.1 88/03/24 16:13:54 src
24: * Initial revision
25: *
26: * 87/11/25 Allan Cornish /usr/src/sys/coh/fs3.c
27: * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr.
28: *
29: * 86/02/01 Allan Cornish
30: * Added code to fwrite() to avoid needless writing of pipe blocks.
31: * Throughput on 6 Mhz AT rose from 30 Kbytes/sec to 79 Kbytes/sec.
32: */
33: #include <sys/coherent.h>
34: #include <sys/buf.h>
35: #include <canon.h>
36: #include <sys/con.h>
37: #include <errno.h>
38: #include <sys/filsys.h>
39: #include <sys/mount.h>
40: #include <sys/io.h>
41: #include <sys/ino.h>
42: #include <sys/inode.h>
43: #include <sys/stat.h>
44:
45: /*
46: * Given an inode, open it.
47: */
48: iopen(ip, mode)
49: register INODE *ip;
50: {
51: register int type;
52:
53: type = ip->i_mode & IFMT;
54: switch (type) {
55: case IFCHR:
56: case IFBLK:
57: iunlock(ip);
58: dopen(ip->i_a.i_rdev, mode, type==IFCHR ? DFCHR : DFBLK);
59: ilock(ip);
60: break;
61: case IFDIR:
62: if ((mode&IPW) != 0) {
63: if (super() == 0)
64: return;
65: if (mode == IPW) {
66: u.u_error = EISDIR;
67: return;
68: }
69: }
70: break;
71: case IFPIPE:
72: popen(ip, mode);
73: break;
74: }
75: }
76:
77: /*
78: * Given an inode, close it.
79: */
80: iclose(ip)
81: register INODE *ip;
82: {
83: ilock(ip);
84: switch (ip->i_mode&IFMT) {
85: case IFBLK:
86: bflush(ip->i_a.i_rdev);
87: case IFCHR:
88: iunlock(ip);
89: dclose(ip->i_a.i_rdev);
90: ilock(ip);
91: break;
92: case IFPIPE:
93: pclose(ip);
94: break;
95: }
96: idetach(ip);
97: }
98:
99: /*
100: * Read from a file described by an inode and an io strucuture.
101: */
102: iread(ip, iop)
103: register INODE *ip;
104: register IO *iop;
105: {
106: if (iop->io_ioc == 0)
107: return;
108: switch (ip->i_mode&IFMT) {
109: case IFCHR:
110: dread(ip->i_a.i_rdev, iop);
111: break;
112: case IFBLK:
113: case IFREG:
114: case IFDIR:
115: fread(ip, iop);
116: break;
117: case IFPIPE:
118: pread(ip, iop);
119: break;
120: default:
121: u.u_error = ENXIO;
122: break;
123: }
124: }
125:
126: /*
127: * Write to a file described by an inode and io structure.
128: */
129: iwrite(ip, iop)
130: register INODE *ip;
131: register IO *iop;
132: {
133: imod(ip); /* write - mtime */
134: icrt(ip); /* write - ctime */
135: if (iop->io_ioc == 0)
136: return;
137: switch (ip->i_mode&IFMT) {
138: case IFCHR:
139: dwrite(ip->i_a.i_rdev, iop);
140: break;
141: case IFBLK:
142: fwrite(ip, iop);
143: break;
144: case IFREG:
145: case IFDIR:
146: if (getment(ip->i_dev, 1) == NULL)
147: return;
148: fwrite(ip, iop);
149: break;
150: case IFPIPE:
151: pwrite(ip, iop);
152: break;
153: default:
154: u.u_error = ENXIO;
155: break;
156: }
157: }
158:
159: /*
160: * Read from a regular or block special file.
161: */
162: fread(ip, iop)
163: INODE *ip;
164: register IO *iop;
165: {
166: #ifdef TINY
167: register unsigned n;
168: register fsize_t res;
169: register unsigned off;
170: register daddr_t lbn;
171: register BUF *bp;
172: register int blk;
173:
174: lbn = blockn(iop->io_seek);
175: off = blocko(iop->io_seek);
176: blk = (ip->i_mode&IFMT) == IFBLK;
177: res = ip->i_size - iop->io_seek;
178: if (blk!=0 || res>iop->io_ioc)
179: res = iop->io_ioc;
180: while (res > 0) {
181: bp = blk ? bread(ip->i_a.i_rdev, lbn, 1) : vread(ip, lbn);
182: if (bp == NULL)
183: return;
184: n = BSIZE - off;
185: if (n > res)
186: n = res;
187: iowrite(iop, FP_OFF(bp->b_faddr)+off, n);
188: brelease(bp);
189: if (u.u_error)
190: return;
191: lbn++;
192: off = 0;
193: res -= n;
194: }
195: /*
196: * Start of daring read ahead code.
197: * Altered to not read ahead on block devices
198: * due to 20% time penalty incurred for such.
199: */
200: #if 0
201: if ( ! blk) {
202: lbn = vmap(ip, lbn);
203: if (lbn > 0)
204: bread(ip->i_dev, lbn, 0);
205: }
206: #endif
207: /*
208: * End of daring read ahead code.
209: */
210: #else
211: register unsigned n;
212: register unsigned i;
213: register fsize_t res;
214: register unsigned off;
215: register dev_t dev;
216: register daddr_t lbn;
217: register daddr_t pbn;
218: register daddr_t abn;
219: register daddr_t zbn;
220: register BUF *bp;
221: register int blk;
222: daddr_t list[NEXREAD];
223:
224: if ((ip->i_mode&IFMT) == IFBLK) {
225: blk = 1;
226: dev = ip->i_a.i_rdev;
227: } else {
228: blk = 0;
229: dev = ip->i_dev;
230: }
231: abn = 0;
232: zbn = 0;
233: lbn = blockn(iop->io_seek);
234: off = blocko(iop->io_seek);
235: res = ip->i_size - iop->io_seek;
236: if (blk!=0 || res>iop->io_ioc)
237: res = iop->io_ioc;
238: if (res <= 0)
239: return;
240: if (res+off <= BSIZE) {
241: bp = blk ? bread(dev, lbn, 1) : vread(ip, lbn);
242: if (bp == NULL)
243: return;
244: iowrite(iop, FP_OFF(bp->b_faddr)+off, (unsigned)res);
245: brelease(bp);
246: return;
247: }
248: while (res > 0) {
249: if (lbn >= zbn) {
250: if ((n=blockn(res+BSIZE-1)) > NEXREAD)
251: n = NEXREAD;
252: if (n <= 0)
253: n = 1;
254: abn = lbn;
255: for (i=0, zbn=lbn; i<n; i++, zbn++) {
256: if (blk != 0)
257: pbn = zbn;
258: else {
259: if ((pbn=vmap(ip, zbn)) < 0)
260: return;
261: if (pbn == 0) {
262: list[i] = -1;
263: continue;
264: }
265: }
266: list[i] = pbn;
267: bread(dev, pbn, 0);
268: }
269: }
270: if ((pbn=list[lbn-abn]) < 0) {
271: bp = bclaim(NODEV, (daddr_t)0);
272: kclear(FP_OFF(bp->b_faddr), BSIZE);
273: } else {
274: if ((bp=bread(dev, pbn, 1)) == NULL)
275: return;
276: }
277: n = BSIZE - off;
278: n = res>n ? n : res;
279: iowrite(iop, FP_OFF(bp->b_faddr)+off, n);
280: brelease(bp);
281: if (u.u_error)
282: return;
283: lbn++;
284: off = 0;
285: res -= n;
286: }
287: #endif
288: }
289:
290: /*
291: * Write to a regular or block special file.
292: */
293: fwrite(ip, iop)
294: INODE *ip;
295: register IO *iop;
296: {
297: register unsigned n;
298: register unsigned off;
299: register daddr_t lbn;
300: register BUF *bp;
301: register int blk;
302: register int com;
303:
304: lbn = blockn(iop->io_seek);
305: off = blocko(iop->io_seek);
306: blk = (ip->i_mode&IFMT) == IFBLK;
307: while (iop->io_ioc > 0) {
308: n = BSIZE - off;
309: n = iop->io_ioc>n ? n : iop->io_ioc;
310: com = off==0 && n==BSIZE;
311: if (blk == 0)
312: bp = aread(ip, lbn, com);
313: else {
314: if (com)
315: bp = bclaim(ip->i_a.i_rdev, lbn);
316: else
317: bp = bread(ip->i_a.i_rdev, lbn, 1);
318: }
319: if (bp == NULL)
320: return;
321: ioread(iop, FP_OFF(bp->b_faddr)+off, n);
322: bp->b_flag |= BFMOD;
323: if (com && ((ip->i_mode&IFMT) != IFPIPE) )
324: bwrite(bp, 0);
325: else
326: brelease(bp);
327: if (u.u_error)
328: return;
329: lbn++;
330: off = 0;
331: if ((iop->io_seek+=n) > ip->i_size)
332: if (blk == 0)
333: ip->i_size = iop->io_seek;
334: }
335: }
336:
337: /*
338: * Given an inode pointer, read the requested virtual block and return
339: * a buffer with the data.
340: */
341: BUF *
342: vread(ip, lb)
343: register INODE *ip;
344: daddr_t lb;
345: {
346: register daddr_t pb;
347: register BUF *bp;
348:
349: if ((pb=vmap(ip, lb)) < 0)
350: return (NULL);
351: if (pb != 0)
352: return (bread(ip->i_dev, pb, 1));
353: bp = bclaim(NODEV, (daddr_t)0);
354: kclear(FP_OFF(bp->b_faddr), BSIZE);
355: return (bp);
356: }
357:
358: /*
359: * Convert the given virtual block to a physical block for the given inode.
360: * If the block does not map onto a physical block because the file is sparse
361: * but it does exist, 0 is returned. If an error is encountered, -1 is
362: * returned.
363: */
364: daddr_t
365: vmap(ip, lb)
366: register INODE *ip;
367: daddr_t lb;
368: {
369: register BUF *bp;
370: register int *lp;
371: daddr_t * dp;
372: daddr_t pb;
373: int list[1+NI];
374:
375: if ((lp=lmap(lb, list)) == NULL)
376: return (-1);
377: pb = ip->i_a.i_addr[*--lp];
378: for (;;) {
379: if (pb==0 || lp==list)
380: return (pb);
381: if ((bp=bread(ip->i_dev, pb, 1)) == NULL)
382: return (0);
383: dp = FP_OFF(bp->b_faddr);
384: pb = dp[*--lp];
385: brelease(bp);
386: candaddr(pb);
387: }
388: }
389:
390: /*
391: * Given an inode pointer, read the requested virtual block and return a
392: * buffer with the data. In sparse files, the necessary blocks are allocated.
393: * If the flag, `fflag' is set, the final buffer is just claimed rather than
394: * read as we are going to change it's contents completely.
395: */
396: BUF *
397: aread(ip, lb, fflag)
398: register INODE *ip;
399: daddr_t lb;
400: {
401: register BUF *bp;
402: register int *lp;
403: register dev_t dev;
404: register int l;
405: register int aflag;
406: register int lflag;
407: daddr_t * dp;
408: daddr_t pb;
409: int list[1+NI];
410:
411: if ((lp=lmap(lb, list)) == NULL)
412: return (NULL);
413: aflag = 0;
414: dev = ip->i_dev;
415: pb = ip->i_a.i_addr[l=*--lp];
416: if (pb == 0) {
417: aflag = 1;
418: if ((pb=balloc(dev)) == 0)
419: return (NULL);
420: ip->i_a.i_addr[l] = pb;
421: }
422: for (;;) {
423: lflag = lp==list;
424: if (aflag==0 && (fflag==0 || lflag==0)) {
425: if ((bp=bread(dev, pb, 1)) == NULL)
426: return (NULL);
427: } else {
428: bp = bclaim(dev, pb);
429: kclear(FP_OFF(bp->b_faddr), BSIZE);
430: bp->b_flag |= BFMOD;
431: }
432: if (lflag)
433: return (bp);
434:
435: aflag = 0;
436: dp = FP_OFF(bp->b_faddr);
437: pb = dp[l=*--lp];
438: candaddr(pb);
439: if (pb == 0) {
440: aflag = 1;
441: if ((pb=balloc(dev)) == 0) {
442: brelease(bp);
443: return (NULL);
444: }
445: dp[l] = pb;
446: candaddr( dp[l] );
447: bp->b_flag |= BFMOD;
448: }
449: brelease(bp);
450: }
451: }
452:
453: /*
454: * Given a block number, `b', store the offsets for the indirect blocks
455: * backwards in the array, `lp', and return a pointer just after the
456: * position where the first offset is stored.
457: */
458: int *
459: lmap(b, lp)
460: register daddr_t b;
461: register int *lp;
462: {
463: register int n;
464:
465: if (b < ND) {
466: *lp++ = b;
467: return (lp);
468: }
469: b -= ND;
470: n = NI;
471: do {
472: if (n-- == 0) {
473: u.u_error = EFBIG;
474: return (NULL);
475: }
476: *lp = nbnrem(b);
477: ++lp;
478: b = nbndiv(b);
479: } while (b--);
480: *lp++ = ND+NI-1-n;
481: return (lp);
482: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.