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