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