|
|
1.1 root 1: /* $Header: /src386/kernel/coh.386/RCS/fs2.c,v 1.10 93/06/14 13:34:40 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 1.10 93/06/14 13:34:40 bin
21: * Hal: kernel 78 update
22: *
23: * Revision 1.5 93/04/14 10:06:31 root
24: * r75
25: *
26: * Revision 1.2 92/01/06 11:59:27 hal
27: * Compile with cc.mwc.
28: *
29: * Revision 1.1 88/03/24 16:13:51 src
30: * Initial revision
31: *
32: * 87/04/29 Allan Cornish /usr/src/sys/coh/fs2.c
33: * Fsminit panic messages now specify the root major and minor device.
34: *
35: * 86/11/19 Allan Cornish /usr/src/sys/coh/fs2.c
36: * setacct() initializes the (new) (IO).io_flag field to 0.
37: *
38: * 85/08/08 Allan Cornish
39: * ialloc() erroneously did a brelease(NULL) if bclaim() returned NULL.
40: * also, sbp->s_fmod was set BEFORE the in-core inode table was updated.
41: * This created a critical race with msync() (called by sync system call).
42: *
43: * 85/04/17 Allan Cornish
44: * eliminated test for rootdev in msync()
45: */
46: #include <sys/coherent.h>
47: #include <sys/acct.h>
48: #include <sys/buf.h>
49: #include <canon.h>
50: #include <sys/con.h>
51: #include <errno.h>
52: #include <sys/filsys.h>
53: #include <sys/ino.h>
54: #include <sys/inode.h>
55: #include <sys/io.h>
56: #include <sys/mount.h>
57: #include <sys/proc.h>
58: #include <sys/stat.h>
59:
60: #define _INODE_BUSY_DUMP 1
61:
62: /*
63: * Initialise filesystem.
64: */
65: fsminit()
66: {
67: register MOUNT *mp;
68:
69: /*
70: * Mount the root file system.
71: */
72: if ( (mp = fsmount(rootdev, ronflag)) == NULL )
73: panic( "fsminit: no rootdev(%d,%d)",
74: major(rootdev), minor(rootdev) );
75:
76: /*
77: * Set system time from the super block.
78: */
79: timer.t_time = mp->m_super.s_time;
80:
81: /*
82: * Access the root directory.
83: */
84: if ( (u.u_rdir = iattach(rootdev, ROOTIN)) == NULL )
85: panic( "fsminit: no / on rootdev(%d,%d)",
86: major(rootdev), minor(rootdev) );
87:
88: /*
89: * Record current directory.
90: */
91: u.u_cdir = u.u_rdir;
92: u.u_cdir->i_refc++;
93: iunlock(u.u_rdir);
94: }
95:
96: /*
97: * Mount the given device.
98: */
99: MOUNT *
100: fsmount(dev, f)
101: register dev_t dev;
102: {
103: register MOUNT *mp;
104: register BUF *bp;
105:
106: if ((mp=kalloc(sizeof(MOUNT))) == NULL) {
107: printf("fsmount(%x,%x): kalloc failed ", dev, f);
108: return NULL;
109: }
110: dopen(dev, (f?IPR:IPR|IPW), DFBLK);
111: if (u.u_error) {
112: printf("fsmount(%x,%x): dopen failed ", dev, f);
113: kfree(mp);
114: return NULL;
115: }
116: if ((bp=bread(dev, (daddr_t)SUPERI, 1)) == NULL) {
117: dclose(dev, (f?IPR:IPR|IPW), DFBLK); /* NIGEL */
118: kfree(mp);
119: return NULL;
120: }
121: kkcopy(bp->b_vaddr, &mp->m_super, sizeof(struct filsys));
122: brelease(bp);
123: cansuper(&mp->m_super);
124: mp->m_ip = NULL;
125: mp->m_dev = dev;
126: mp->m_flag = f;
127: mp->m_super.s_fmod = 0;
128: mp->m_next = mountp;
129: mountp = mp;
130: return (mp);
131: }
132:
133: /*
134: * Canonize a super block.
135: */
136: cansuper(fsp)
137: register struct filsys *fsp;
138: {
139: register int i;
140:
141: canint(fsp->s_isize);
142: candaddr(fsp->s_fsize);
143: canshort(fsp->s_nfree);
144: for (i=0; i<NICFREE; i++)
145: candaddr(fsp->s_free[i]);
146: canshort(fsp->s_ninode);
147: for (i=0; i<NICINOD; i++)
148: canino(fsp->s_inode[i]);
149: cantime(fsp->s_time);
150: candaddr(fsp->s_tfree);
151: canino(fsp->s_tinode);
152: canshort(fsp->s_m);
153: canshort(fsp->s_n);
154: canlong(fsp->s_unique);
155: }
156:
157: /*
158: * Given a pointer to a mount entry, write out all inodes on that device.
159: */
160: msync(mp)
161: register MOUNT *mp;
162: {
163: register struct filsys *sbp;
164: register BUF *bp;
165:
166: if ((mp->m_flag&MFRON) != 0)
167: return;
168: isync(mp->m_dev);
169: sbp = &mp->m_super;
170: if (sbp->s_fmod==0)
171: return;
172: bp = bclaim(mp->m_dev, (daddr_t)SUPERI);
173: sbp->s_time = timer.t_time;
174: sbp->s_fmod = 0;
175: kkcopy(sbp, bp->b_vaddr, sizeof(*sbp));
176: cansuper(bp->b_vaddr);
177: bwrite(bp, 1);
178: brelease(bp);
179: }
180:
181: /*
182: * Return the mount entry for the given device. If `f' is not set
183: * and the device is read only, don't set the error status.
184: */
185: MOUNT *
186: getment(dev, f)
187: register dev_t dev;
188: {
189: register MOUNT *mp;
190:
191: for (mp=mountp; mp!=NULL; mp=mp->m_next) {
192: if (mp->m_dev != dev)
193: continue;
194: if ((mp->m_flag&MFRON) != 0) {
195: if (f != 0)
196: u.u_error = EROFS;
197: return NULL;
198: }
199: return (mp);
200: }
201: panic("getment: dev=0x%x", dev);
202: }
203:
204: /*
205: * Allocate a new inode with the given mode. The returned inode is locked.
206: */
207: INODE *
208: ialloc(dev, mode)
209: dev_t dev;
210: unsigned mode;
211: {
212: register struct dinode *dip;
213: register struct filsys *sbp;
214: register ino_t *inop;
215: register ino_t ino;
216: register BUF *bp;
217: register daddr_t b;
218: register struct dinode *dipe;
219: register ino_t *inope;
220: register MOUNT *mp;
221: register INODE *ip;
222: #if _INODE_BUSY_DUMP
223: int eninode, etinode;
224: int lninode, ltinode;
225: int xninode, xtinode;
226: #endif
227:
228: if ((mp=getment(dev, 1)) == NULL)
229: return NULL;
230: sbp = &mp->m_super;
231:
232: #if _INODE_BUSY_DUMP
233: eninode = sbp->s_ninode;
234: etinode = sbp->s_tinode;
235: #endif
236:
237: for (;;) {
238: lock(mp->m_ilock);
239:
240: #if _INODE_BUSY_DUMP
241: lninode = sbp->s_ninode;
242: ltinode = sbp->s_tinode;
243: #endif
244:
245: if (sbp->s_ninode == 0) {
246: isync(dev);
247: ino = 1;
248: inop = sbp->s_inode;
249: inope = &sbp->s_inode[NICINOD];
250: for (b=INODEI; b<sbp->s_isize; b++) {
251: if (bad(dev, b)) {
252: ino += INOPB;
253: continue;
254: }
255: if ((bp=bread(dev, b, 1)) == NULL) {
256: ino += INOPB;
257: continue;
258: }
259: dip = bp->b_vaddr;
260: dipe = &dip[INOPB];
261: for (; dip<dipe; dip++, ino++) {
262: if (dip->di_mode != 0)
263: continue;
264: if (inop >= inope)
265: break;
266: *inop++ = ino;
267: }
268: brelease(bp);
269: if (inop >= inope)
270: break;
271: }
272: sbp->s_ninode = inop - sbp->s_inode;
273: if (sbp->s_ninode == 0) {
274: sbp->s_tinode = 0;
275: unlock(mp->m_ilock);
276: devmsg(dev, "Out of inodes");
277: u.u_error = ENOSPC;
278: return NULL;
279: }
280: }
281:
282: #if _INODE_BUSY_DUMP
283: xninode = sbp->s_ninode;
284: xtinode = sbp->s_tinode;
285: #endif
286:
287: ino = sbp->s_inode[--sbp->s_ninode];
288: --sbp->s_tinode;
289: sbp->s_fmod = 1;
290: unlock(mp->m_ilock);
291: if ((ip=iattach(dev, ino)) != NULL) {
292: if (ip->i_mode != 0) {
293: devmsg(dev, "Inode %u busy", ino);
294:
295: #if _INODE_BUSY_DUMP
296: 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",
297: mode, ino, ip->i_refc, ip->i_flag, ip->i_mode, ip->i_nlink,
298: eninode, etinode, lninode, ltinode, xninode, xtinode,
299: sbp->s_ninode, sbp->s_tinode);
300: #endif
301:
302: idetach(ip);
303: lock(mp->m_ilock);
304: ++sbp->s_tinode;
305: sbp->s_fmod = 1;
306: unlock(mp->m_ilock);
307: continue;
308: }
309: ip->i_flag = 0;
310: ip->i_mode = mode;
311: ip->i_nlink = 0;
312: ip->i_uid = u.u_uid;
313: ip->i_gid = u.u_gid;
314: }
315: return (ip);
316: }
317: }
318:
319: /*
320: * Free the inode `ino' on device `dev'.
321: */
322: ifree(dev, ino)
323: dev_t dev;
324: ino_t ino;
325: {
326: register struct filsys *sbp;
327: register MOUNT *mp;
328:
329: if ((mp=getment(dev, 1)) == NULL)
330: return;
331: lock(mp->m_ilock);
332: sbp = &mp->m_super;
333: sbp->s_fmod = 1;
334: if (sbp->s_ninode < NICINOD)
335: sbp->s_inode[sbp->s_ninode++] = ino;
336: sbp->s_tinode++;
337: unlock(mp->m_ilock);
338: }
339:
340: /*
341: * Free all blocks in the indirect block `b' on the device `dev'.
342: * `l' is the level of indirection.
343: */
344: indfree(dev, b, l)
345: dev_t dev;
346: daddr_t b;
347: register unsigned l;
348: {
349: register int i;
350: register BUF *bp;
351: daddr_t * dp;
352: daddr_t b1;
353:
354: if (b == 0)
355: return;
356: if (l-->0 && (bp=bread(dev, b, 1))!=NULL) {
357: i = NBN;
358: while (i-- > 0) {
359: dp = bp->b_vaddr;
360: if ((b1 = dp[i]) == 0)
361: continue;
362: candaddr(b1);
363: if (l == 0)
364: bfree(dev, b1);
365: else
366: indfree(dev, b1, l);
367: }
368: brelease(bp);
369: }
370: bfree(dev, b);
371: }
372:
373: /*
374: * Allocate a block from the filesystem mounted of device `dev'.
375: */
376: daddr_t
377: balloc(dev)
378: dev_t dev;
379: {
380: register struct filsys *sbp;
381: register struct fblk *fbp;
382: register daddr_t b;
383: register BUF *bp;
384: register MOUNT *mp;
385:
386: if ((mp=getment(dev, 1)) == NULL)
387: return (0);
388: lock(mp->m_flock);
389: sbp = &mp->m_super;
390: if (sbp->s_nfree == 0) {
391: enospc:
392: sbp->s_nfree = 0;
393: devmsg(dev, "Out of space");
394: u.u_error = ENOSPC;
395: b = 0;
396: } else {
397: sbp->s_fmod = 1;
398: if ((b=sbp->s_free[--sbp->s_nfree]) == 0)
399: goto enospc;
400: if (sbp->s_nfree == 0) {
401: if (b >= sbp->s_fsize
402: || b < sbp->s_isize
403: || (bp = bread(dev, b, 1)) == NULL) {
404: ebadflist:
405: devmsg(dev, "Bad free list");
406: goto enospc;
407: }
408: fbp = bp->b_vaddr;
409: sbp->s_nfree = fbp->df_nfree;
410: canshort(sbp->s_nfree);
411: if ((unsigned)sbp->s_nfree > NICFREE)
412: goto ebadflist;
413: kkcopy(fbp->df_free, sbp->s_free, sizeof(sbp->s_free));
414: canndaddr(sbp->s_free, sbp->s_nfree);
415: brelease(bp);
416: }
417: --sbp->s_tfree;
418: if (b >= sbp->s_fsize || b < sbp->s_isize)
419: goto ebadflist;
420: }
421: unlock(mp->m_flock);
422: return (b);
423: }
424:
425: /*
426: * Free the block `b' on the device `dev'.
427: */
428: bfree(dev, b)
429: dev_t dev;
430: daddr_t b;
431: {
432: register struct filsys *sbp;
433: register struct fblk *fbp;
434: register BUF *bp;
435: register MOUNT *mp;
436:
437: if ((mp=getment(dev, 1)) == NULL)
438: return;
439: sbp = &mp->m_super;
440: if (b>=sbp->s_fsize || b<sbp->s_isize) {
441: devmsg(dev, "Bad block %u (free)", (unsigned)b);
442: return;
443: }
444: lock(mp->m_flock);
445: if (sbp->s_nfree == 0 || sbp->s_nfree == NICFREE) {
446: bp = bclaim(dev, b);
447: kclear(bp->b_vaddr, BSIZE);
448: fbp = bp->b_vaddr;
449: fbp->df_nfree = sbp->s_nfree;
450: canshort(fbp->df_nfree);
451: kkcopy(sbp->s_free, fbp->df_free, sizeof(fbp->df_free));
452: canndaddr(fbp->df_free, sbp->s_nfree);
453: bp->b_flag |= BFMOD;
454: brelease(bp);
455: sbp->s_nfree = 0;
456: }
457: sbp->s_free[sbp->s_nfree++] = b;
458: sbp->s_tfree++;
459: sbp->s_fmod = 1;
460: unlock(mp->m_flock);
461: }
462:
463: /*
464: * Determine if the given block is bad.
465: */
466: bad(dev, b)
467: dev_t dev;
468: daddr_t b;
469: {
470: register INODE *ip;
471: register BUF *bp;
472: register int i;
473: register int m;
474: register int n;
475: daddr_t l;
476:
477: if ((ip=iattach(dev, 1)) == NULL)
478: panic("bad()");
479: n = blockn(ip->i_size);
480: if ((m=n) > ND)
481: m = ND;
482: for (i=0; i<m; i++) {
483: --n;
484: if (b == ip->i_a.i_addr[i]) {
485: idetach(ip);
486: return (1);
487: }
488: }
489: l = ip->i_a.i_addr[ND];
490: idetach(ip);
491: if (n == 0)
492: return (0);
493: if ((bp=bread(dev, l, 1)) == NULL)
494: return (0);
495: if ((m=n) > NBN)
496: m = NBN;
497: for (i=0; i<m; i++) {
498: l = ((daddr_t *)bp)[i];
499: candaddr(l);
500: if (b == l) {
501: brelease(bp);
502: return (1);
503: }
504: }
505: brelease(bp);
506: return (0);
507: }
508:
509: /*
510: * Canonize `n' disk addresses.
511: */
512: canndaddr(dp, n)
513: register daddr_t *dp;
514: register int n;
515: {
516: while (n--) {
517: candaddr(*dp);
518: dp++;
519: }
520: }
521:
522: /*
523: * Convert long to comp_t style number.
524: * A comp_t contains 3 bits of base-8 exponent
525: * and a 13-bit mantissa. Only unsigned
526: * numbers can be comp_t numbers.
527: */
528:
529: #define MAXMANT 017777 /* 2^13-1 = largest mantissa */
530:
531: static comp_t
532: ltoc(l)
533: long l;
534: {
535: register int exp;
536:
537: if (l < 0)
538: return (0);
539: for (exp = 0; l > MAXMANT; exp++)
540: l >>= 3;
541: return ((exp<<13) | l);
542: }
543:
544: /*
545: * Write out an accounting record.
546: */
547: setacct()
548: {
549: register PROC *pp;
550: struct acct acct;
551: IO acctio;
552:
553: if (acctip == NULL)
554: return;
555: pp = SELF;
556: kkcopy(u.u_comm, acct.ac_comm, 10);
557: acct.ac_utime = ltoc(pp->p_utime);
558: acct.ac_stime = ltoc(pp->p_stime);
559: acct.ac_etime = ltoc(timer.t_time - u.u_btime);
560: acct.ac_btime = u.u_btime;
561: acct.ac_uid = u.u_uid;
562: acct.ac_gid = u.u_gid;
563: acct.ac_mem = 0;
564: acct.ac_io = ltoc(u.u_block);
565: acct.ac_tty = pp->p_ttdev;
566: acct.ac_flag = u.u_flag;
567: ilock(acctip);
568: acctio.io_seek = acctip->i_size;
569: acctio.io_ioc = sizeof (acct);
570: acctio.io.vbase = &acct;
571: acctio.io_seg = IOSYS;
572: acctio.io_flag = 0;
573: iwrite(acctip, &acctio);
574: iunlock(acctip);
575: u.u_error = 0;
576: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.