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