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