|
|
1.1 root 1: /* $Header: /src386/STREAMS/coh.386/RCS/fs2.c,v 2.3 93/08/09 13:35:33 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 (disk inodes).
18: *
19: * $Log: fs2.c,v $
20: * Revision 2.3 93/08/09 13:35:33 bin
21: * Kernel 82 changes
22: *
23: * Revision 2.2 93/07/26 15:19:24 nigel
24: * Nigel's R80
25: *
26: * Revision 2.2 93/07/26 14:28:32 nigel
27: * Nigel's R80
28: *
29: * Revision 1.5 93/04/14 10:06:31 root
30: * r75
31: *
32: * Revision 1.2 92/01/06 11:59:27 hal
33: * Compile with cc.mwc.
34: *
35: * Revision 1.1 88/03/24 16:13:51 src
36: * Initial revision
37: *
38: * 87/04/29 Allan Cornish /usr/src/sys/coh/fs2.c
39: * Fsminit panic messages now specify the root major and minor device.
40: *
41: * 86/11/19 Allan Cornish /usr/src/sys/coh/fs2.c
42: * setacct() initializes the (new) (IO).io_flag field to 0.
43: *
44: * 85/08/08 Allan Cornish
45: * ialloc() erroneously did a brelease(NULL) if bclaim() returned NULL.
46: * also, sbp->s_fmod was set BEFORE the in-core inode table was updated.
47: * This created a critical race with msync() (called by sync system call).
48: *
49: * 85/04/17 Allan Cornish
50: * eliminated test for rootdev in msync()
51: */
52:
53: #include <common/ccompat.h>
54: #include <sys/debug.h>
55:
56: #include <sys/coherent.h>
57: #include <sys/acct.h>
58: #include <sys/buf.h>
59: #include <canon.h>
60: #include <sys/con.h>
61: #include <sys/errno.h>
62: #include <sys/filsys.h>
63: #include <sys/ino.h>
64: #include <sys/inode.h>
65: #include <sys/io.h>
66: #include <sys/mount.h>
67: #include <sys/proc.h>
68: #include <sys/stat.h>
69: #include <sys/file.h>
70:
71: #define _INODE_BUSY_DUMP 1
72:
73: /*
74: * Initialise filesystem.
75: */
76: fsminit()
77: {
78: register MOUNT *mp;
79: INODE * ip;
80:
81: /*
82: * NIGEL: We begin by setting up all the inodes in the system.
83: */
84:
85: for (ip = inodep + NINODE - 1 ; ip >= inodep ; ip --) {
86: ip->i_refc = 0;
87: __GATE_INIT (ip->i_gate, "inode");
88: }
89:
90:
91: /*
92: * Mount the root file system.
93: */
94: if ((mp = fsmount (rootdev, ronflag)) == NULL)
95: panic ("fsminit: no rootdev(%d,%d)",
96: major (rootdev), minor (rootdev));
97:
98: /*
99: * Set system time from the super block.
100: */
101: timer.t_time = mp->m_super.s_time;
102:
103: /*
104: * Access the root directory.
105: */
106: if ((u.u_rdir = iattach (rootdev, ROOTIN)) == NULL)
107: panic ("fsminit: no / on rootdev(%d,%d)",
108: major (rootdev), minor (rootdev));
109:
110: /*
111: * Record current directory.
112: */
113: u.u_cdir = u.u_rdir;
114: u.u_cdir->i_refc++;
115: iunlock (u.u_rdir);
116: }
117:
118:
119: /*
120: * Mount the given device.
121: */
122: MOUNT *
123: fsmount(dev, f)
124: register dev_t dev;
125: {
126: register MOUNT *mp;
127: register BUF *bp;
128:
129: if ((mp = kalloc (sizeof (MOUNT))) == NULL) {
130: printf ("fsmount(%x,%x): kalloc failed ", dev, f);
131: return NULL;
132: }
133: dopen (dev, (f ? IPR : IPR | IPW), DFBLK);
134: if (u.u_error) {
135: printf("fsmount(%x,%x): dopen failed ", dev, f);
136: kfree (mp);
137: return NULL;
138: }
139: if ((bp = bread (dev, (daddr_t) SUPERI, BUF_SYNC)) == NULL) {
140: dclose (dev, (f ? IPR : IPR | IPW), DFBLK); /* NIGEL */
141: kfree (mp);
142: return NULL;
143: }
144: memcpy (& mp->m_super, bp->b_vaddr, sizeof (mp->m_super));
145: brelease (bp);
146: cansuper (& mp->m_super);
147:
148: mp->m_ip = NULL;
149: mp->m_dev = dev;
150: mp->m_flag = f;
151: mp->m_super.s_fmod = 0;
152: mp->m_next = mountp;
153:
154: __GATE_INIT (mp->m_ilock, "mount ilock");
155: __GATE_INIT (mp->m_flock, "mount flock");
156:
157: mountp = mp;
158: return mp;
159: }
160:
161:
162: /*
163: * Canonize a super block.
164: */
165: cansuper(fsp)
166: register struct filsys *fsp;
167: {
168: register int i;
169:
170: canint (fsp->s_isize);
171: candaddr (fsp->s_fsize);
172: canshort (fsp->s_nfree);
173: for (i = 0 ; i < NICFREE ; i ++)
174: candaddr (fsp->s_free [i]);
175: canshort (fsp->s_ninode);
176: for (i = 0 ; i < NICINOD ; i ++)
177: canino (fsp->s_inode [i]);
178: cantime (fsp->s_time);
179: candaddr (fsp->s_tfree);
180: canino (fsp->s_tinode);
181: canshort (fsp->s_m);
182: canshort (fsp->s_n);
183: canlong (fsp->s_unique);
184: }
185:
186: /*
187: * Given a pointer to a mount entry, write out all inodes on that device.
188: */
189: msync(mp)
190: register MOUNT *mp;
191: {
192: register struct filsys *sbp;
193: register BUF *bp;
194:
195: if ((mp->m_flag & MFRON) != 0)
196: return;
197: isync (mp->m_dev);
198: sbp = & mp->m_super;
199: if (sbp->s_fmod == 0)
200: return;
201: bp = bclaim (mp->m_dev, (daddr_t) SUPERI, BUF_SYNC);
202: sbp->s_time = timer.t_time;
203: sbp->s_fmod = 0;
204: memcpy (bp->b_vaddr, sbp, sizeof (* sbp));
205: cansuper (bp->b_vaddr);
206: bwrite (bp, 1);
207: brelease (bp);
208: }
209:
210: /*
211: * Return the mount entry for the given device. If `f' is not set
212: * and the device is read only, don't set the error status.
213: */
214: MOUNT *
215: getment(dev, f)
216: register dev_t dev;
217: {
218: register MOUNT *mp;
219:
220: for (mp = mountp ; mp != NULL ; mp = mp->m_next) {
221: if (mp->m_dev != dev)
222: continue;
223: if ((mp->m_flag & MFRON) != 0) {
224: if (f != 0)
225: u.u_error = EROFS;
226: return NULL;
227: }
228: return mp;
229: }
230: panic ("getment: dev=0x%x", dev);
231: }
232:
233: /*
234: * Allocate a new inode with the given mode. The returned inode is locked.
235: */
236: INODE *
237: ialloc(dev, mode)
238: dev_t dev;
239: unsigned mode;
240: {
241: register struct dinode *dip;
242: register struct filsys *sbp;
243: register ino_t *inop;
244: register ino_t ino;
245: register BUF *bp;
246: register daddr_t b;
247: register struct dinode *dipe;
248: register ino_t *inope;
249: register MOUNT *mp;
250: register INODE *ip;
251: #if _INODE_BUSY_DUMP
252: int eninode, etinode;
253: int lninode, ltinode;
254: int xninode, xtinode;
255: #endif
256:
257: if ((mp = getment (dev, 1)) == NULL)
258: return NULL;
259: sbp = & mp->m_super;
260:
261: #if _INODE_BUSY_DUMP
262: eninode = sbp->s_ninode;
263: etinode = sbp->s_tinode;
264: #endif
265:
266: for (;;) {
267: lock (mp->m_ilock);
268:
269: #if _INODE_BUSY_DUMP
270: lninode = sbp->s_ninode;
271: ltinode = sbp->s_tinode;
272: #endif
273:
274: if (sbp->s_ninode == 0) {
275: isync (dev);
276: ino = 1;
277: inop = sbp->s_inode;
278: inope = & sbp->s_inode [NICINOD];
279: for (b = INODEI ; b < sbp->s_isize ; b ++) {
280: if (bad (dev, b)) {
281: ino += INOPB;
282: continue;
283: }
284: if ((bp = bread (dev, b, BUF_SYNC)) == NULL) {
285: ino += INOPB;
286: continue;
287: }
288: dip = bp->b_vaddr;
289: dipe = & dip [INOPB];
290: for (; dip < dipe ; dip ++, ino ++) {
291: if (dip->di_mode != 0)
292: continue;
293: if (inop >= inope)
294: break;
295: * inop ++ = ino;
296: }
297: brelease (bp);
298: if (inop >= inope)
299: break;
300: }
301: sbp->s_ninode = inop - sbp->s_inode;
302: if (sbp->s_ninode == 0) {
303: sbp->s_tinode = 0;
304: unlock (mp->m_ilock);
305: devmsg (dev, "Out of inodes");
306: u.u_error = ENOSPC;
307: return NULL;
308: }
309: }
310:
311: #if _INODE_BUSY_DUMP
312: xninode = sbp->s_ninode;
313: xtinode = sbp->s_tinode;
314: #endif
315:
316: ino = sbp->s_inode [-- sbp->s_ninode];
317: -- sbp->s_tinode;
318: sbp->s_fmod = 1;
319: unlock (mp->m_ilock);
320: if ((ip = iattach(dev, ino)) != NULL) {
321: if (ip->i_mode != 0) {
322: devmsg(dev, "Inode %u busy", ino);
323:
324: #if _INODE_BUSY_DUMP
325: printf("%x %x rf=%x fl=%x md=%x nl=%x en=%x et=%x ln=%x lt=%x xn=%x xt=%x n=%x t=%x\n",
326: mode, ino, ip->i_refc, ip->i_flag, ip->i_mode, ip->i_nlink,
327: eninode, etinode, lninode, ltinode, xninode, xtinode,
328: sbp->s_ninode, sbp->s_tinode);
329: #endif
330:
331: idetach (ip);
332: lock (mp->m_ilock);
333: ++ sbp->s_tinode;
334: sbp->s_fmod = 1;
335: unlock (mp->m_ilock);
336: continue;
337: }
338: ip->i_flag = 0;
339: ip->i_mode = mode;
340: ip->i_nlink = 0;
341: ip->i_uid = u.u_uid;
342: ip->i_gid = u.u_gid;
343: }
344: return ip;
345: }
346: }
347:
348: /*
349: * Free the inode `ino' on device `dev'.
350: */
351: ifree(dev, ino)
352: dev_t dev;
353: ino_t ino;
354: {
355: register struct filsys *sbp;
356: register MOUNT *mp;
357:
358: if ((mp = getment(dev, 1)) == NULL)
359: return;
360: lock (mp->m_ilock);
361: sbp = & mp->m_super;
362: sbp->s_fmod = 1;
363: if (sbp->s_ninode < NICINOD)
364: sbp->s_inode [sbp->s_ninode ++] = ino;
365: sbp->s_tinode ++;
366: unlock (mp->m_ilock);
367: }
368:
369: /*
370: * Free all blocks in the indirect block `b' on the device `dev'.
371: * `l' is the level of indirection.
372: */
373: indfree(dev, b, l)
374: dev_t dev;
375: daddr_t b;
376: register unsigned l;
377: {
378: register int i;
379: register BUF *bp;
380: daddr_t * dp;
381: daddr_t b1;
382:
383: if (b == 0)
384: return;
385: if (l -- > 0 && (bp = bread (dev, b, BUF_SYNC)) != NULL) {
386: i = NBN;
387: while (i -- > 0) {
388: dp = bp->b_vaddr;
389: if ((b1 = dp [i]) == 0)
390: continue;
391: candaddr (b1);
392: if (l == 0)
393: bfree (dev, b1);
394: else
395: indfree (dev, b1, l);
396: }
397: brelease (bp);
398: }
399: bfree (dev, b);
400: }
401:
402: /*
403: * Experimental routine to read free block lists blocks (ahead of time, but
404: * if it works we'll subsume the synchronous read as well).
405: */
406:
407: static BUF *
408: read_free_block_list (super, dev, block_no, sync_flag)
409: struct filsys * super;
410: dev_t dev;
411: daddr_t block_no;
412: int sync_flag;
413: {
414: return block_no < super->s_fsize && block_no >= super->s_isize ?
415: bread (dev, block_no, sync_flag) : NULL;
416: }
417:
418:
419: /*
420: * Allocate a block from the filesystem mounted of device `dev'.
421: */
422:
423: daddr_t
424: balloc(dev)
425: dev_t dev;
426: {
427: register struct filsys *sbp;
428: register struct fblk *fbp;
429: register daddr_t b;
430: register BUF *bp;
431: register MOUNT *mp;
432:
433: if ((mp = getment(dev, 1)) == NULL)
434: return 0;
435: lock (mp->m_flock);
436: sbp = & mp->m_super;
437: if (sbp->s_nfree == 0) {
438: enospc:
439: sbp->s_nfree = 0;
440: devmsg (dev, "Out of space");
441: u.u_error = ENOSPC;
442: b = 0;
443: } else {
444: sbp->s_fmod = 1;
445: if ((b = sbp->s_free [-- sbp->s_nfree]) == 0)
446: goto enospc;
447: if (sbp->s_nfree == 0) {
448: if ((bp = read_free_block_list (sbp, dev, b,
449: BUF_SYNC)) == NULL) {
450: ebadflist:
451: devmsg(dev, "Bad free list");
452: goto enospc;
453: }
454: fbp = bp->b_vaddr;
455: sbp->s_nfree = fbp->df_nfree;
456: canshort (sbp->s_nfree);
457: memcpy (sbp->s_free, fbp->df_free,
458: sizeof (sbp->s_free));
459:
460: if (sbp->s_nfree > NICFREE)
461: goto ebadflist;
462: brelease (bp);
463:
464: canndaddr (sbp->s_free, sbp->s_nfree);
465:
466: /*
467: * NIGEL: As an experiment, try reading ahead on the
468: * free block list.
469: */
470:
471: if (sbp->s_nfree > 0)
472: read_free_block_list (sbp, dev,
473: sbp->s_free [0],
474: BUF_ASYNC);
475: }
476: -- sbp->s_tfree;
477: if (b >= sbp->s_fsize || b < sbp->s_isize)
478: goto ebadflist;
479: }
480: unlock (mp->m_flock);
481: return b;
482: }
483:
484:
485: /*
486: * Flag to say whether we should try and keep the free-block list sorted.
487: */
488:
489: int t_sortblocks = 0;
490:
491: /*
492: * If we are sorting blocks, this routine can be used to keep blocks in sorted
493: * order. Given a fixed-size list in reverse rank order, this routine returns
494: * the new element if it is smaller than all others, or the smallest element
495: * after the new element has been inserted in position.
496: */
497:
498: #if __USE_PROTO__
499: static daddr_t daddr_add (daddr_t * list, int count, daddr_t newblock)
500: #else
501: static daddr_t
502: daddr_add (list, count, newblock)
503: daddr_t * list;
504: int count;
505: daddr_t newblock;
506: #endif
507: {
508: daddr_t * end = list + count;
509:
510: ASSERT (count >= 0);
511:
512: while (list != end) {
513: if (newblock < * list ++) {
514: daddr_t temp;
515: /*
516: * We have found the insertion point... move all the
517: * elements from (list - 1) to (end - 1) up, and put
518: * the new element in place.
519: */
520:
521: temp = * -- end;
522: list --;
523:
524: while (list != end) {
525: end --;
526: * (end + 1) = * end;
527: }
528: * list = newblock;
529: return temp;
530: }
531: }
532:
533: return newblock;
534: }
535:
536:
537: /*
538: * Free the block `b' on the device `dev'.
539: */
540: bfree(dev, b)
541: dev_t dev;
542: daddr_t b;
543: {
544: register struct filsys *sbp;
545: register struct fblk *fbp;
546: register BUF *bp;
547: register MOUNT *mp;
548:
549: if ((mp = getment (dev, 1)) == NULL)
550: return;
551: sbp = & mp->m_super;
552: if (b >= sbp->s_fsize || b < sbp->s_isize) {
553: devmsg (dev, "Bad block %u (free)", (unsigned) b);
554: return;
555: }
556:
557: /*
558: * NIGEL : Are we keeping things in order? If so, insert the new block
559: * in position (the smallest block-number is the new 'b'). Note that
560: * the zero-position of the free-block list never changes... this is
561: * an important invariant, because the block in that position is a
562: * link and *must* be preserved in that position so that the links get
563: * properly followed later on.
564: */
565:
566: if (t_sortblocks && sbp->s_nfree > 0)
567: b = daddr_add (sbp->s_free + 1, sbp->s_nfree - 1, b);
568:
569: lock (mp->m_flock);
570: if (sbp->s_nfree == 0 || sbp->s_nfree == NICFREE) {
571: bp = bclaim (dev, b, BUF_SYNC);
572: fbp = bp->b_vaddr;
573:
574: /*
575: * NIGEL: Is there really any reason to do this?
576: */
577: memset (bp->b_vaddr, 0, BSIZE);
578:
579: fbp->df_nfree = sbp->s_nfree;
580: canshort (fbp->df_nfree);
581: memcpy (fbp->df_free, sbp->s_free, sizeof (fbp->df_free));
582: canndaddr (fbp->df_free, sbp->s_nfree);
583:
584: bp->b_flag |= BFMOD;
585: brelease (bp);
586: sbp->s_nfree = 0;
587: }
588: sbp->s_free [sbp->s_nfree ++] = b;
589: sbp->s_tfree ++;
590: sbp->s_fmod = 1;
591: unlock (mp->m_flock);
592: }
593:
594: /*
595: * Determine if the given block is bad.
596: */
597: bad(dev, b)
598: dev_t dev;
599: daddr_t b;
600: {
601: register INODE *ip;
602: register BUF *bp;
603: register int i;
604: register int m;
605: register int n;
606: daddr_t l;
607:
608: if ((ip = iattach (dev, 1)) == NULL)
609: panic ("bad()");
610: n = blockn (ip->i_size);
611: if ((m = n) > ND)
612: m = ND;
613: for (i = 0 ; i < m ; i ++) {
614: -- n;
615: if (b == ip->i_a.i_addr [i]) {
616: idetach (ip);
617: return 1;
618: }
619: }
620: l = ip->i_a.i_addr [ND];
621: idetach (ip);
622: if (n == 0)
623: return 0;
624: if ((bp = bread (dev, l, BUF_SYNC)) == NULL)
625: return 0;
626: if ((m = n) > NBN)
627: m = NBN;
628: for (i = 0 ; i < m ; i ++) {
629: l = ((daddr_t *) bp) [i];
630: candaddr (l);
631: if (b == l) {
632: brelease (bp);
633: return 1;
634: }
635: }
636: brelease (bp);
637: return 0;
638: }
639:
640: /*
641: * Canonize `n' disk addresses.
642: */
643: canndaddr(dp, n)
644: register daddr_t *dp;
645: register int n;
646: {
647: while (n --) {
648: candaddr (* dp);
649: dp ++;
650: }
651: }
652:
653: /*
654: * Convert long to comp_t style number.
655: * A comp_t contains 3 bits of base-8 exponent
656: * and a 13-bit mantissa. Only unsigned
657: * numbers can be comp_t numbers.
658: */
659:
660: #define MAXMANT 017777 /* 2^13-1 = largest mantissa */
661:
662: static comp_t
663: ltoc(l)
664: long l;
665: {
666: register int exp;
667:
668: if (l < 0)
669: return 0;
670: for (exp = 0 ; l > MAXMANT ; exp ++)
671: l >>= 3;
672: return (exp << 13) | l;
673: }
674:
675: /*
676: * Write out an accounting record.
677: */
678: setacct()
679: {
680: register PROC *pp;
681: struct acct acct;
682: IO acctio;
683:
684: if (acctip == NULL)
685: return;
686: pp = SELF;
687: kkcopy(u.u_comm, acct.ac_comm, 10);
688: acct.ac_utime = ltoc(pp->p_utime);
689: acct.ac_stime = ltoc(pp->p_stime);
690: acct.ac_etime = ltoc(timer.t_time - u.u_btime);
691: acct.ac_btime = u.u_btime;
692: acct.ac_uid = u.u_uid;
693: acct.ac_gid = u.u_gid;
694: acct.ac_mem = 0;
695: acct.ac_io = ltoc(u.u_block);
696: acct.ac_tty = pp->p_ttdev;
697: acct.ac_flag = u.u_flag;
698: ilock(acctip);
699: acctio.io_seek = acctip->i_size;
700: acctio.io_ioc = sizeof (acct);
701: acctio.io.vbase = &acct;
702: acctio.io_seg = IOSYS;
703: acctio.io_flag = 0;
704: iwrite(acctip, &acctio);
705: iunlock(acctip);
706: u.u_error = 0;
707: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.