|
|
1.1 root 1: #include "sys/param.h"
2: #include "sys/systm.h"
3: #include "sys/filsys.h"
4: #include "sys/fblk.h"
5: #include "sys/buf.h"
6: #include "sys/inode.h"
7: #include "sys/ino.h"
8: #include "sys/user.h"
9:
10: typedef struct fblk *FP;
11:
12: /*
13: * alloc will obtain the next available
14: * free disk block from the free list of
15: * the specified filsys.
16: * The super block has up to NICFREE remembered
17: * free blocks; the last of these is read to
18: * obtain NICFREE more . . .
19: */
20: static daddr_t bitfsalloc(), oldfsalloc(), bigfsalloc();
21:
22: struct buf *
23: alloc(fip, prev)
24: struct inode *fip;
25: daddr_t prev;
26: {
27: daddr_t bno;
28: register struct filsys *fp;
29: register struct buf *bp;
30:
31: fp = getfs(fip);
32: while (fp->s_flock)
33: sleep((caddr_t)&fp->s_flock, PINOD);
34: if(BITFS(fip->i_dev)) /* unfortunately device dependent */
35: if(fp->U.N.S_flag)
36: bno = bigfsalloc(fp, prev);
37: else
38: bno = bitfsalloc(fp, prev);
39: else
40: bno = oldfsalloc(fp, fip->i_dev);
41: if (bno == 0) {
42: /*fp->s_nfree = 0; /* but it would be wrong FIX*/
43: fp->s_tfree = 0;
44: fserr(fip->i_dev, fp, "file system full");
45: tsleep((caddr_t)&u, PRIBIO, 5); /* slow things down */
46: u.u_error = ENOSPC;
47: return (NULL);
48: }
49: bp = getblk(fip->i_dev, bno);
50: clrbuf(bp);
51: fp->s_fmod = 1;
52: fp->s_tfree--;
53: return (bp);
54: }
55:
56: /*
57: * bitmap fs alloc:
58: * given the previous block in the file,
59: * try to pick one in the same cylinder,
60: * preferably in a nice rotational place
61: * if we can't, pick one in the next couple of cylinders
62: * if we can't, just pick any block
63: */
64:
65: static daddr_t
66: bitfsalloc(fp, prev)
67: register struct filsys *fp;
68: daddr_t prev;
69: {
70: register daddr_t bno;
71: register long i;
72: daddr_t cyl, end, best;
73:
74: best = -1;
75: if (fp->s_cylsize == 0) { /* safety for the root. ugh. */
76: fp->s_cylsize = 40;
77: fp->s_aspace = 4; /* good for comets */
78: }
79: if (prev >= fp->s_isize) {
80: bno = prev / fp->s_cylsize;
81: bno *= fp->s_cylsize;
82: if (bno < fp->s_isize)
83: bno = fp->s_isize;
84: cyl = bno + fp->s_cylsize;
85: end = bno + 3 * fp->s_cylsize;
86: if (end > fp->s_fsize)
87: end = fp->s_fsize;
88: if (cyl > fp->s_fsize)
89: cyl = fp->s_fsize;
90: i = bno - fp->s_isize;
91: best = findbit(fp->s_bfree, i, cyl-fp->s_isize, prev-fp->s_isize,
92: fp->s_aspace); /* in same cylinder */
93: if(best == -1)
94: best = findbit(fp->s_bfree, cyl-fp->s_isize,
95: end-fp->s_isize, 0L, 0);
96: }
97: if(best == -1)
98: best = findbit(fp->s_bfree, 0L, fp->s_fsize-fp->s_isize, 0L, 0);
99: if(best == -1)
100: return(0);
101: BITALLOC(fp->s_bfree, best);
102: if (fp->s_valid) {
103: fp->s_valid = 0;
104: update(); /* ugh */
105: }
106: return (best+fp->s_isize);
107: }
108:
109: /*
110: * new-style, multi-segment bitmap
111: * take care not to cross segment boundaries
112: */
113:
114: static daddr_t
115: bigfsalloc(fp, prev)
116: register struct filsys *fp;
117: daddr_t prev;
118: {
119: register int fblk;
120: register long bs;
121: register long best, beg, cyl;
122: int nblk;
123:
124: bs = fp->U.N.S_bsize;
125: if(prev > 0) {
126: beg = prev/fp->s_cylsize;
127: beg *= fp->s_cylsize;
128: if(beg < fp->s_isize)
129: beg = fp->s_isize; /* unnecessary */
130: cyl = beg + fp->s_cylsize;
131: if(cyl > fp->s_fsize)
132: cyl = fp->s_fsize;
133: fblk = beg/bs;
134: if (fblk != (cyl-1)/bs)
135: cyl = (fblk+1)*bs; /* bound to this block */
136: best = findbit(fp->U.N.S_blk[fblk]->b_un.b_words, beg%bs,
137: cyl%bs, prev%bs, fp->s_aspace);
138: if (best != -1)
139: goto done;
140: beg = cyl;
141: cyl = beg + 2 * fp->s_cylsize;
142: if (cyl >= fp->s_fsize)
143: cyl = fp->s_fsize;
144: fblk = beg/bs;
145: if (fblk != (cyl - 1)/bs)
146: cyl = (fblk+1)*bs;
147: best = findbit(fp->U.N.S_blk[fblk]->b_un.b_words, beg%bs,
148: cyl%bs, 0L, 0);
149: if(best != -1)
150: goto done;
151: }
152: /*
153: * find any free bit at all
154: */
155: nblk = (fp->s_fsize + bs - 1) / bs;
156: for (fblk = 0; fblk < nblk; fblk++) {
157: best = findbit(fp->U.N.S_blk[fblk]->b_un.b_words, 0L, bs, 0L, 0);
158: if(best != -1)
159: goto done;
160: }
161: /*
162: * found nothing nowhere
163: */
164: return(0);
165: /*
166: * found bit best in block fblk
167: */
168: done:
169: BITALLOC((fp->U.N.S_blk[fblk]->b_un.b_words), best);
170: if(fp->s_valid) {
171: fp->s_valid = 0;
172: update();
173: }
174: return(best+fblk*bs);
175: }
176:
177: /* find a bit between bot and top, preferably at least space from prev */
178: findbit(ptr, bot, top, prev, space)
179: long *ptr;
180: long bot, top, prev;
181: {
182: register long *p;
183: register int j;
184: register long bno, best;
185:
186: best = -1;
187: j = bot/BITCELL;
188: p = ptr + j;
189: bno = j*BITCELL; /* start on long boundary */
190: for(; bno < top; p++) {
191: if(*p == 0) { /* none free in whole long */
192: bno += BITCELL; /* so onward */
193: continue;
194: }
195: for(j = 0; j < BITCELL; j++, bno++) {
196: if((*p & (1<<j)) == 0)
197: continue;
198: if(bno < bot || bno >= top) /* out of the loop? */
199: continue; /* first and last longs */
200: if(best == -1)
201: best = bno;
202: if(bno - prev >= space)
203: return(bno);
204: }
205: }
206: return(best); /* -1 or whatever we found */
207: }
208:
209: static daddr_t
210: oldfsalloc(fp, dev)
211: register struct filsys *fp;
212: {
213: register daddr_t bno;
214: register struct buf *bp;
215:
216: do {
217: if (fp->s_nfree <= 0)
218: return (0);
219: if (fp->s_nfree > NICFREE) {
220: fserr(dev, fp, "bad free count");
221: return (0);
222: }
223: bno = fp->s_free[--fp->s_nfree];
224: if (bno == 0)
225: return (0);
226: } while (badblock(dev, fp, bno));
227: if (fp->s_nfree <= 0) {
228: fp->s_flock++;
229: bp = bread(dev, bno);
230: if ((bp->b_flags&B_ERROR) == 0) {
231: fp->s_nfree = ((FP)(bp->b_un.b_addr))->df_nfree;
232: bcopy((caddr_t)((FP)(bp->b_un.b_addr))->df_free,
233: (caddr_t)fp->s_free, sizeof(fp->s_free));
234: }
235: brelse(bp);
236: fp->s_flock = 0;
237: wakeup((caddr_t)&fp->s_flock);
238: if (fp->s_nfree <= 0)
239: return (0);
240: }
241: return (bno);
242: }
243:
244: /*
245: * place the specified disk block
246: * back on the free list of the
247: * specified device.
248: */
249: free(fip, bno)
250: struct inode *fip;
251: daddr_t bno;
252: { int bs;
253: register struct filsys *fp;
254: register struct buf *bp;
255:
256: fp = getfs(fip);
257: fp->s_fmod = 1;
258: while (fp->s_flock)
259: sleep((caddr_t)&fp->s_flock, PINOD);
260: if (badblock(fip->i_dev, fp, bno))
261: return;
262: if(BITFS(fip->i_dev)) {
263: /* paranoia suggests checking it's not already free */
264: if(fp->U.N.S_flag) {
265: bs = fp->U.N.S_bsize;
266: BITFREE((fp->U.N.S_blk[bno/bs]->b_un.b_words), bno%bs);
267: }
268: else {
269: bno -= fp->s_isize;
270: BITFREE(fp->s_bfree, bno);
271: }
272: if(fp->s_valid) { /* not any more */
273: fp->s_valid = 0;
274: update(); /* even GROSSER */
275: }
276: }
277: else {
278: if (fp->s_nfree <= 0) {
279: fp->s_nfree = 1;
280: fp->s_free[0] = 0;
281: }
282: if (fp->s_nfree >= NICFREE) {
283: fp->s_flock++;
284: bp = getblk(fip->i_dev, bno);
285: ((FP)(bp->b_un.b_addr))->df_nfree = fp->s_nfree;
286: bcopy((caddr_t)fp->s_free,
287: (caddr_t)((FP)(bp->b_un.b_addr))->df_free,
288: sizeof(fp->s_free));
289: fp->s_nfree = 0;
290: bwrite(bp);
291: fp->s_flock = 0;
292: wakeup((caddr_t)&fp->s_flock);
293: }
294: fp->s_free[fp->s_nfree++] = bno;
295: }
296: fp->s_tfree++;
297: fp->s_fmod = 1;
298: }
299:
300: /*
301: * Check that a block number is in the
302: * range between the I list and the size
303: * of the device.
304: * This is used mainly to check that a
305: * garbage file system has not been mounted.
306: */
307: badblock(dev, fp, bn)
308: dev_t dev;
309: register struct filsys *fp;
310: daddr_t bn;
311: {
312:
313: if (bn < fp->s_isize || bn >= fp->s_fsize) {
314: fserr(dev, fp, "bad block");
315: return(1);
316: }
317: return(0);
318: }
319:
320: /*
321: * allocate an unused disk inode in the specified filesystem
322: * up to NICINOD possible i-numbers are kept in a list
323: * in s_inode; try those first. If the list empties,
324: * scan the i-list and fill it again.
325: * To speed things up, pick up the scan where it last
326: * left off (s_lasti) unless there are believed to be
327: * many free i-nodes with lower numbers (s_nbehind).
328: * s_ilock is there only to avoid having two processes
329: * in the list-filling code.
330: */
331:
332: int dupinod; /* debug */
333:
334: struct inode *
335: ialloc(fip)
336: struct inode *fip;
337: {
338: register struct filsys *fp;
339: register struct buf *bp;
340: register struct inode *ip;
341: register int i;
342: struct dinode *dp;
343: ino_t ino;
344: int first;
345: int inopb;
346: daddr_t adr;
347:
348: fp = getfs(fip);
349: if (fp->s_ninode > NICINOD || fp->s_ninode < 0) {
350: fserr(fip->i_dev, fp, "bad inode count");
351: fp->s_ninode = 0;
352: }
353: loop:
354: if (fp->s_ninode > 0) {
355: ino = fp->s_inode[--fp->s_ninode];
356: if (ifind(fip, ino)) { /* already in use */
357: dupinod++; /* debug */
358: goto loop;
359: }
360: ip = iget(fip, fip->i_dev, ino);
361: if (ip == NULL) /* probably table full */
362: return(NULL);
363: if (ip->i_count == 1 && fsiread(fip, ip) < 0)
364: goto loop;
365: if (ip->i_mode != 0) { /* already allocated */
366: iput(ip);
367: goto loop;
368: }
369: for (i=0; i<NADDR; i++)
370: ip->i_un.i_addr[i] = 0;
371: fp->s_tinode--;
372: fp->s_fmod = 1;
373: return(ip);
374: }
375: /*
376: * nothing left in super-block; restock
377: */
378: while (fp->s_ilock)
379: sleep((caddr_t)&fp->s_ilock, PINOD);
380: if (fp->s_ninode > 0) /* someone beat us to it? */
381: goto loop;
382: fp->s_ilock++;
383: first = 1;
384: inopb = INOPB(fip->i_dev); /* optimization */
385: fromtop:
386: ino = fp->s_lasti;
387: ino = ((ino / inopb) * inopb) + 1; /* round down to start of block */
388: adr = itod(fip->i_dev, ino);
389: if (fp->s_nbehind > 4 * NICINOD
390: || adr <= SUPERB || adr >= fp->s_isize
391: || first == 0) {
392: first = 0;
393: ino = 1;
394: adr = SUPERB + 1;
395: fp->s_nbehind = 0;
396: }
397: for(; adr < fp->s_isize; adr++) {
398: bp = bread(fip->i_dev, adr);
399: if (bp->b_flags & B_ERROR) {
400: brelse(bp);
401: ino += inopb;
402: continue;
403: }
404: dp = bp->b_un.b_dino;
405: for (i=0; i<inopb; i++, ino++, dp++) {
406: if (dp->di_mode != 0 || ifind(fip, ino))
407: continue;
408: fp->s_inode[fp->s_ninode++] = ino;
409: if (fp->s_ninode >= NICINOD)
410: break;
411: }
412: brelse(bp);
413: if (fp->s_ninode >= NICINOD)
414: break;
415: }
416: /*
417: * if we found nothing,
418: * try again from the beginning of the i-list
419: */
420: if (fp->s_ninode <= 0 && first) {
421: first = 0;
422: goto fromtop;
423: }
424: if (fp->s_ninode == NICINOD)
425: fp->s_lasti = ino;
426: else { /* hit the end, but found something */
427: fp->s_lasti = 1;
428: fp->s_nbehind = 0;
429: }
430: fp->s_ilock = 0;
431: wakeup((caddr_t)&fp->s_ilock);
432: if (fp->s_ninode > 0)
433: goto loop;
434: fserr(fip->i_dev, fp, "out of inodes");
435: u.u_error = ENOSPC;
436: return (NULL);
437: }
438:
439: /*
440: * Free the specified inode on the specified device.
441: * The algorithm stores up to NICINOD inodes in the super
442: * block and throws away any more. It keeps track of the
443: * number of inodes thrown away which preceded the current
444: * search point in the file system. This lets us rescan
445: * for more inodes from the beginning only when there
446: * are a reasonable number of inodes back there to reallocate.
447: */
448:
449: ifree(ip)
450: register struct inode *ip;
451: {
452: register struct filsys *fp;
453:
454: fp = getfs(ip);
455: if (fp->s_ninode > NICINOD || fp->s_ninode < 0) {
456: fserr(ip->i_dev, fp, "bad inode count");
457: fp->s_ninode = 0;
458: }
459: fp->s_tinode++;
460: if (fp->s_ilock)
461: return;
462: if (fp->s_ninode >= NICINOD) {
463: if (fp->s_lasti > ip->i_number)
464: fp->s_nbehind++;
465: return;
466: }
467: fp->s_inode[fp->s_ninode++] = ip->i_number;
468: fp->s_fmod = 1;
469: }
470:
471: /*
472: * getfs maps an inode into
473: * a pointer to the incore super
474: * block.
475: *
476: * panic: no fs -- the device is not mounted.
477: * this "cannot happen"
478: */
479: struct filsys *
480: getfs(fip)
481: register struct inode *fip;
482: {
483:
484: if (fip->i_fstyp != 0 || fip->i_un.i_bufp == NULL)
485: panic("no fs");
486: return (fip->i_un.i_bufp->b_un.b_filsys);
487: }
488:
489: /*
490: * Fserr prints the name of a file system
491: * with an error diagnostic, in the form
492: * filsys: error message
493: */
494: fserr(dev, fp, cp)
495: dev_t dev;
496: struct filsys *fp;
497: char *cp;
498: {
499:
500: printf("0%o,0%o %s: %s\n", major(dev), minor(dev), fp->s_fsmnt, cp);
501: }
502:
503: /*
504: * Update is the internal name of 'sync'. It goes through the disk
505: * queues to initiate sandbagged IO; goes through the inodes to write
506: * modified nodes; and it goes through the mount table to initiate modified
507: * super blocks.
508: */
509: update()
510: {
511: register struct inode *ip;
512: static int updlock;
513:
514: if (updlock)
515: return;
516: updlock++;
517: /*
518: * Write back each (modified) inode.
519: */
520: for (ip = inode; ip < inodeNINODE; ip++)
521: if((ip->i_flag&ILOCK)==0 && ip->i_count) {
522: ip->i_flag |= ILOCK;
523: ip->i_count++;
524: iupdat(ip, &time, &time, 0);
525: iput(ip);
526: }
527: updlock = 0;
528: /*
529: * Force stale buffer cache information to be flushed,
530: * for all devices.
531: */
532: bflush(NODEV);
533: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.