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