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