|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)mkfs.c 6.6 (Berkeley) 4/24/88";
9: #endif not lint
10:
11: /*
12: * make file system for cylinder-group style file systems
13: */
14:
15: #ifndef STANDALONE
16: #include <stdio.h>
17: #include <a.out.h>
18: #endif
19:
20: #include <sys/param.h>
21: #include <sys/inode.h>
22: #include <sys/fs.h>
23: #include <sys/dir.h>
24: #include <sys/disklabel.h>
25:
26: #define UMASK 0755
27: #define MAXINOPB (MAXBSIZE / sizeof(struct dinode))
28: #define POWEROF2(num) (((num) & ((num) - 1)) == 0)
29:
30: /*
31: * variables set up by front end.
32: */
33: extern int Nflag; /* run mkfs without writing file system */
34: extern int fssize; /* file system size */
35: extern int ntracks; /* # tracks/cylinder */
36: extern int nsectors; /* # sectors/track */
37: extern int nphyssectors; /* # sectors/track including spares */
38: extern int secpercyl; /* sectors per cylinder */
39: extern int sectorsize; /* bytes/sector */
40: extern int rpm; /* revolutions/minute of drive */
41: extern int interleave; /* hardware sector interleave */
42: extern int trackskew; /* sector 0 skew, per track */
43: extern int headswitch; /* head switch time, usec */
44: extern int trackseek; /* track-to-track seek, usec */
45: extern int fsize; /* fragment size */
46: extern int bsize; /* block size */
47: extern int cpg; /* cylinders/cylinder group */
48: extern int cpgflg; /* cylinders/cylinder group flag was given */
49: extern int minfree; /* free space threshold */
50: extern int opt; /* optimization preference (space or time) */
51: extern int density; /* number of bytes per inode */
52: extern int maxcontig; /* max contiguous blocks to allocate */
53: extern int rotdelay; /* rotational delay between blocks */
54: extern int maxbpg; /* maximum blocks per file in a cyl group */
55: extern int bbsize; /* boot block size */
56: extern int sbsize; /* superblock size */
57:
58: union {
59: struct fs fs;
60: char pad[MAXBSIZE];
61: } fsun;
62: #define sblock fsun.fs
63: struct csum *fscs;
64:
65: union {
66: struct cg cg;
67: char pad[MAXBSIZE];
68: } cgun;
69: #define acg cgun.cg
70:
71: struct dinode zino[MAXIPG];
72:
73: int fsi, fso;
74: time_t utime;
75: daddr_t alloc();
76:
77: mkfs(pp, fsys, fi, fo)
78: struct partition *pp;
79: char *fsys;
80: int fi, fo;
81: {
82: register long i, mincpc, mincpg, inospercg;
83: long cylno, rpos, blk, j, warn = 0;
84: long used, mincpgcnt, bpcg;
85: long mapcramped, inodecramped;
86:
87: #ifndef STANDALONE
88: time(&utime);
89: #endif
90: fsi = fi;
91: fso = fo;
92: /*
93: * Validate the given file system size.
94: * Verify that its last block can actually be accessed.
95: */
96: if (fssize <= 0)
97: printf("preposterous size %d\n", fssize), exit(1);
98: wtfs(fssize - 1, sectorsize, (char *)&sblock);
99: /*
100: * collect and verify the sector and track info
101: */
102: sblock.fs_nsect = nsectors;
103: sblock.fs_ntrak = ntracks;
104: if (sblock.fs_ntrak <= 0)
105: printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1);
106: if (sblock.fs_nsect <= 0)
107: printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1);
108: /*
109: * collect and verify the block and fragment sizes
110: */
111: sblock.fs_bsize = bsize;
112: sblock.fs_fsize = fsize;
113: if (!POWEROF2(sblock.fs_bsize)) {
114: printf("block size must be a power of 2, not %d\n",
115: sblock.fs_bsize);
116: exit(1);
117: }
118: if (!POWEROF2(sblock.fs_fsize)) {
119: printf("fragment size must be a power of 2, not %d\n",
120: sblock.fs_fsize);
121: exit(1);
122: }
123: if (sblock.fs_fsize < sectorsize) {
124: printf("fragment size %d is too small, minimum is %d\n",
125: sblock.fs_fsize, sectorsize);
126: exit(1);
127: }
128: if (sblock.fs_bsize < MINBSIZE) {
129: printf("block size %d is too small, minimum is %d\n",
130: sblock.fs_bsize, MINBSIZE);
131: exit(1);
132: }
133: if (sblock.fs_bsize < sblock.fs_fsize) {
134: printf("block size (%d) cannot be smaller than fragment size (%d)\n",
135: sblock.fs_bsize, sblock.fs_fsize);
136: exit(1);
137: }
138: sblock.fs_bmask = ~(sblock.fs_bsize - 1);
139: sblock.fs_fmask = ~(sblock.fs_fsize - 1);
140: for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1)
141: sblock.fs_bshift++;
142: for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1)
143: sblock.fs_fshift++;
144: sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize);
145: for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1)
146: sblock.fs_fragshift++;
147: if (sblock.fs_frag > MAXFRAG) {
148: printf("fragment size %d is too small, minimum with block size %d is %d\n",
149: sblock.fs_fsize, sblock.fs_bsize,
150: sblock.fs_bsize / MAXFRAG);
151: exit(1);
152: }
153: sblock.fs_nindir = sblock.fs_bsize / sizeof(daddr_t);
154: sblock.fs_inopb = sblock.fs_bsize / sizeof(struct dinode);
155: sblock.fs_nspf = sblock.fs_fsize / sectorsize;
156: for (sblock.fs_fsbtodb = 0, i = NSPF(&sblock); i > 1; i >>= 1)
157: sblock.fs_fsbtodb++;
158: sblock.fs_sblkno =
159: roundup(howmany(bbsize + sbsize, sblock.fs_fsize), sblock.fs_frag);
160: sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno +
161: roundup(howmany(sbsize, sblock.fs_fsize), sblock.fs_frag));
162: sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag;
163: sblock.fs_cgoffset = roundup(
164: howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag);
165: for (sblock.fs_cgmask = 0xffffffff, i = sblock.fs_ntrak; i > 1; i >>= 1)
166: sblock.fs_cgmask <<= 1;
167: if (!POWEROF2(sblock.fs_ntrak))
168: sblock.fs_cgmask <<= 1;
169: /*
170: * Validate specified/determined secpercyl
171: * and calculate minimum cylinders per group.
172: */
173: sblock.fs_spc = secpercyl;
174: for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc;
175: sblock.fs_cpc > 1 && (i & 1) == 0;
176: sblock.fs_cpc >>= 1, i >>= 1)
177: /* void */;
178: mincpc = sblock.fs_cpc;
179: if (mincpc > MAXCPG) {
180: printf("Maximum frag size with %d sectors per cylinder is %d\n",
181: sblock.fs_spc, sblock.fs_fsize / (mincpc / MAXCPG));
182: exit(1);
183: }
184: bpcg = sblock.fs_spc * sectorsize;
185: inospercg = roundup(bpcg / sizeof(struct dinode), INOPB(&sblock));
186: if (inospercg > MAXIPG)
187: inospercg = MAXIPG;
188: used = (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock);
189: mincpgcnt = howmany(sblock.fs_cgoffset * (~sblock.fs_cgmask) + used,
190: sblock.fs_spc);
191: mincpg = roundup(mincpgcnt, mincpc);
192: /*
193: * Insure that cylinder group with mincpg has enough space
194: * for block maps
195: */
196: mapcramped = 0;
197: while (mincpg * sblock.fs_spc > MAXBPG(&sblock) * NSPB(&sblock)) {
198: mapcramped = 1;
199: if (sblock.fs_bsize < MAXBSIZE) {
200: sblock.fs_bsize <<= 1;
201: if ((i & 1) == 0) {
202: i >>= 1;
203: } else {
204: sblock.fs_cpc <<= 1;
205: mincpc <<= 1;
206: mincpg = roundup(mincpgcnt, mincpc);
207: }
208: sblock.fs_frag <<= 1;
209: sblock.fs_fragshift += 1;
210: if (sblock.fs_frag <= MAXFRAG)
211: continue;
212: }
213: if (sblock.fs_fsize == sblock.fs_bsize) {
214: printf("There is no block size that");
215: printf(" can support this disk\n");
216: exit(1);
217: }
218: sblock.fs_frag >>= 1;
219: sblock.fs_fragshift -= 1;
220: sblock.fs_fsize <<= 1;
221: sblock.fs_nspf <<= 1;
222: }
223: /*
224: * Insure that cylinder group with mincpg has enough space for inodes
225: */
226: inodecramped = 0;
227: used *= sectorsize;
228: inospercg = (mincpg * bpcg - used) / density;
229: while (inospercg > MAXIPG) {
230: inodecramped = 1;
231: if (mincpc == 1 || sblock.fs_frag == 1 ||
232: sblock.fs_bsize == MINBSIZE)
233: break;
234: printf("With a block size of %d %s %d\n", sblock.fs_bsize,
235: "minimum bytes per inode is",
236: (mincpg * bpcg - used) / MAXIPG + 1);
237: sblock.fs_bsize >>= 1;
238: sblock.fs_frag >>= 1;
239: sblock.fs_fragshift -= 1;
240: mincpc >>= 1;
241: i = roundup(mincpgcnt, mincpc);
242: if (i * sblock.fs_spc > MAXBPG(&sblock) * NSPB(&sblock)) {
243: sblock.fs_bsize <<= 1;
244: break;
245: }
246: mincpg = i;
247: inospercg = (mincpg * bpcg - used) / density;
248: }
249: if (inodecramped) {
250: if (inospercg > MAXIPG) {
251: printf("Minimum bytes per inode is %d\n",
252: (mincpg * bpcg - used) / MAXIPG + 1);
253: } else if (!mapcramped) {
254: printf("With %d bytes per inode, ", density);
255: printf("minimum cylinders per group is %d\n", mincpg);
256: }
257: }
258: if (mapcramped) {
259: printf("With %d sectors per cylinder, ", sblock.fs_spc);
260: printf("minimum cylinders per group is %d\n", mincpg);
261: }
262: if (inodecramped || mapcramped) {
263: if (sblock.fs_bsize != bsize)
264: printf("%s to be changed from %d to %d\n",
265: "This requires the block size",
266: bsize, sblock.fs_bsize);
267: if (sblock.fs_fsize != fsize)
268: printf("\t%s to be changed from %d to %d\n",
269: "and the fragment size",
270: bsize, sblock.fs_bsize);
271: exit(1);
272: }
273: /*
274: * Calculate the number of cylinders per group
275: */
276: sblock.fs_cpg = cpg;
277: if (sblock.fs_cpg % mincpc != 0) {
278: printf("%s groups must have a multiple of %d cylinders\n",
279: cpgflg ? "Cylinder" : "Warning: cylinder", mincpc);
280: sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc);
281: }
282: /*
283: * Must insure there is enough space to hold block map
284: */
285: sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
286: while (sblock.fs_fpg > MAXBPG(&sblock) * sblock.fs_frag) {
287: mapcramped = 1;
288: sblock.fs_cpg -= mincpc;
289: sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
290: }
291: /*
292: * Must insure there is enough space for inodes
293: */
294: inospercg = (sblock.fs_cpg * bpcg - used) / density;
295: while (inospercg > MAXIPG) {
296: inodecramped = 1;
297: sblock.fs_cpg -= mincpc;
298: sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
299: inospercg = (sblock.fs_cpg * bpcg - used) / density;
300: }
301: if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) {
302: printf("newfs: panic (fs_cpg * fs_spc) % NSPF != 0");
303: exit(2);
304: }
305: if (sblock.fs_cpg < mincpg) {
306: printf("cylinder groups must have at least %d cylinders\n",
307: mincpg);
308: exit(1);
309: } else if (sblock.fs_cpg > MAXCPG) {
310: printf("cylinder groups are limited to %d cylinders\n", MAXCPG);
311: exit(1);
312: } else if (sblock.fs_cpg != cpg) {
313: if (!cpgflg)
314: printf("Warning: ");
315: if (mapcramped && inodecramped)
316: printf("Block size and bytes per inode restrict");
317: else if (mapcramped)
318: printf("Block size restricts");
319: else
320: printf("Bytes per inode restrict");
321: printf(" cylinders per group to %d.\n", sblock.fs_cpg);
322: if (cpgflg)
323: exit(1);
324: }
325: sblock.fs_cgsize = fragroundup(&sblock,
326: sizeof(struct cg) + howmany(sblock.fs_fpg, NBBY));
327: /*
328: * Now have size for file system and nsect and ntrak.
329: * Determine number of cylinders and blocks in the file system.
330: */
331: sblock.fs_size = fssize = dbtofsb(&sblock, fssize);
332: sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc;
333: if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) {
334: sblock.fs_ncyl++;
335: warn = 1;
336: }
337: if (sblock.fs_ncyl < 1) {
338: printf("file systems must have at least one cylinder\n");
339: exit(1);
340: }
341: /*
342: * determine feasability/values of rotational layout tables
343: */
344: sblock.fs_interleave = interleave;
345: sblock.fs_trackskew = trackskew;
346: sblock.fs_npsect = nphyssectors;
347: if (sblock.fs_ntrak == 1) {
348: sblock.fs_cpc = 0;
349: goto next;
350: }
351: if (sblock.fs_spc * sblock.fs_cpc > MAXBPC * NSPB(&sblock) ||
352: sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) {
353: printf("%s %s %d %s %d.%s",
354: "Warning: insufficient space in super block for\n",
355: "rotational layout tables with nsect", sblock.fs_nsect,
356: "and ntrak", sblock.fs_ntrak,
357: "\nFile system performance may be impaired.\n");
358: sblock.fs_cpc = 0;
359: goto next;
360: }
361: /*
362: * calculate the available blocks for each rotational position
363: */
364: for (cylno = 0; cylno < MAXCPG; cylno++)
365: for (rpos = 0; rpos < NRPOS; rpos++)
366: sblock.fs_postbl[cylno][rpos] = -1;
367: blk = sblock.fs_spc * sblock.fs_cpc / NSPF(&sblock);
368: for (i = 0; i < blk; i += sblock.fs_frag)
369: /* void */;
370: for (i -= sblock.fs_frag; i >= 0; i -= sblock.fs_frag) {
371: cylno = cbtocylno(&sblock, i);
372: rpos = cbtorpos(&sblock, i);
373: blk = i / sblock.fs_frag;
374: if (sblock.fs_postbl[cylno][rpos] == -1)
375: sblock.fs_rotbl[blk] = 0;
376: else
377: sblock.fs_rotbl[blk] =
378: sblock.fs_postbl[cylno][rpos] - blk;
379: sblock.fs_postbl[cylno][rpos] = blk;
380: }
381: next:
382: /*
383: * Compute/validate number of cylinder groups.
384: */
385: sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg;
386: if (sblock.fs_ncyl % sblock.fs_cpg)
387: sblock.fs_ncg++;
388: /*
389: * Compute number of inode blocks per cylinder group.
390: */
391: sblock.fs_ipg = roundup(inospercg, INOPB(&sblock));
392: if (sblock.fs_ipg > MAXIPG) {
393: printf("newfs: panic fs_ipg > MAXIPG");
394: exit(3);
395: }
396: sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock);
397: i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1);
398: if (cgdmin(&sblock, i) - cgbase(&sblock, i) >= sblock.fs_fpg) {
399: printf("inode blocks/cyl group (%d) >= data blocks (%d)\n",
400: cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag,
401: sblock.fs_fpg / sblock.fs_frag);
402: printf("number of cylinders per cylinder group (%d) %s.\n",
403: sblock.fs_ncg, "must be increased");
404: exit(1);
405: }
406: j = sblock.fs_ncg - 1;
407: if ((i = fssize - j * sblock.fs_fpg) < sblock.fs_fpg &&
408: cgdmin(&sblock, j) - cgbase(&sblock, j) > i) {
409: printf("Warning: inode blocks/cyl group (%d) >= data blocks (%d) in last\n",
410: (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag,
411: i / sblock.fs_frag);
412: printf(" cylinder group. This implies %d sector(s) cannot be allocated.\n",
413: i * NSPF(&sblock));
414: sblock.fs_ncg--;
415: sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg;
416: sblock.fs_size = fssize = sblock.fs_ncyl * sblock.fs_spc /
417: NSPF(&sblock);
418: warn = 0;
419: }
420: if (warn) {
421: printf("Warning: %d sector(s) in last cylinder unallocated\n",
422: sblock.fs_spc -
423: (fssize * NSPF(&sblock) - (sblock.fs_ncyl - 1)
424: * sblock.fs_spc));
425: }
426: /*
427: * fill in remaining fields of the super block
428: */
429: sblock.fs_csaddr = cgdmin(&sblock, 0);
430: sblock.fs_cssize =
431: fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum));
432: i = sblock.fs_bsize / sizeof(struct csum);
433: sblock.fs_csmask = ~(i - 1);
434: for (sblock.fs_csshift = 0; i > 1; i >>= 1)
435: sblock.fs_csshift++;
436: i = sizeof(struct fs) +
437: howmany(sblock.fs_spc * sblock.fs_cpc, NSPB(&sblock));
438: sblock.fs_sbsize = fragroundup(&sblock, i);
439: fscs = (struct csum *)calloc(1, sblock.fs_cssize);
440: sblock.fs_magic = FS_MAGIC;
441: sblock.fs_rotdelay = rotdelay;
442: sblock.fs_minfree = minfree;
443: sblock.fs_maxcontig = maxcontig;
444: sblock.fs_headswitch = headswitch;
445: sblock.fs_trkseek = trackseek;
446: sblock.fs_maxbpg = maxbpg;
447: sblock.fs_rps = rpm / 60;
448: sblock.fs_optim = opt;
449: sblock.fs_cgrotor = 0;
450: sblock.fs_cstotal.cs_ndir = 0;
451: sblock.fs_cstotal.cs_nbfree = 0;
452: sblock.fs_cstotal.cs_nifree = 0;
453: sblock.fs_cstotal.cs_nffree = 0;
454: sblock.fs_fmod = 0;
455: sblock.fs_ronly = 0;
456: /*
457: * Dump out summary information about file system.
458: */
459: printf("%s:\t%d sectors in %d cylinders of %d tracks, %d sectors\n",
460: fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl,
461: sblock.fs_ntrak, sblock.fs_nsect);
462: printf("\t%.1fMb in %d cyl groups (%d c/g, %.2fMb/g, %d i/g)\n",
463: (float)sblock.fs_size * sblock.fs_fsize * 1e-6, sblock.fs_ncg,
464: sblock.fs_cpg, (float)sblock.fs_fpg * sblock.fs_fsize * 1e-6,
465: sblock.fs_ipg);
466: /*
467: * Now build the cylinders group blocks and
468: * then print out indices of cylinder groups.
469: */
470: printf("super-block backups (for fsck -b#) at:");
471: for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
472: initcg(cylno);
473: if (cylno % 9 == 0)
474: printf("\n");
475: printf(" %d,", fsbtodb(&sblock, cgsblock(&sblock, cylno)));
476: }
477: printf("\n");
478: if (Nflag)
479: exit(0);
480: /*
481: * Now construct the initial file system,
482: * then write out the super-block.
483: */
484: fsinit();
485: sblock.fs_time = utime;
486: wtfs(SBOFF / sectorsize, sbsize, (char *)&sblock);
487: for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize)
488: wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)),
489: sblock.fs_cssize - i < sblock.fs_bsize ?
490: sblock.fs_cssize - i : sblock.fs_bsize,
491: ((char *)fscs) + i);
492: /*
493: * Write out the duplicate super blocks
494: */
495: for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
496: wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)),
497: sbsize, (char *)&sblock);
498: /*
499: * Update information about this partion in pack
500: * label, to that it may be updated on disk.
501: */
502: pp->p_fstype = FS_BSDFFS;
503: pp->p_fsize = sblock.fs_fsize;
504: pp->p_frag = sblock.fs_frag;
505: pp->p_cpg = sblock.fs_cpg;
506: }
507:
508: /*
509: * Initialize a cylinder group.
510: */
511: initcg(cylno)
512: int cylno;
513: {
514: daddr_t cbase, d, dlower, dupper, dmax;
515: long i, j, s;
516: register struct csum *cs;
517:
518: /*
519: * Determine block bounds for cylinder group.
520: * Allow space for super block summary information in first
521: * cylinder group.
522: */
523: cbase = cgbase(&sblock, cylno);
524: dmax = cbase + sblock.fs_fpg;
525: if (dmax > sblock.fs_size)
526: dmax = sblock.fs_size;
527: dlower = cgsblock(&sblock, cylno) - cbase;
528: dupper = cgdmin(&sblock, cylno) - cbase;
529: cs = fscs + cylno;
530: acg.cg_time = utime;
531: acg.cg_magic = CG_MAGIC;
532: acg.cg_cgx = cylno;
533: if (cylno == sblock.fs_ncg - 1)
534: acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
535: else
536: acg.cg_ncyl = sblock.fs_cpg;
537: acg.cg_niblk = sblock.fs_ipg;
538: acg.cg_ndblk = dmax - cbase;
539: acg.cg_cs.cs_ndir = 0;
540: acg.cg_cs.cs_nffree = 0;
541: acg.cg_cs.cs_nbfree = 0;
542: acg.cg_cs.cs_nifree = 0;
543: acg.cg_rotor = 0;
544: acg.cg_frotor = 0;
545: acg.cg_irotor = 0;
546: for (i = 0; i < sblock.fs_frag; i++) {
547: acg.cg_frsum[i] = 0;
548: }
549: for (i = 0; i < sblock.fs_ipg; ) {
550: for (j = INOPB(&sblock); j > 0; j--) {
551: clrbit(acg.cg_iused, i);
552: i++;
553: }
554: acg.cg_cs.cs_nifree += INOPB(&sblock);
555: }
556: if (cylno == 0)
557: for (i = 0; i < ROOTINO; i++) {
558: setbit(acg.cg_iused, i);
559: acg.cg_cs.cs_nifree--;
560: }
561: while (i < MAXIPG) {
562: clrbit(acg.cg_iused, i);
563: i++;
564: }
565: wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno)),
566: sblock.fs_ipg * sizeof (struct dinode), (char *)zino);
567: for (i = 0; i < MAXCPG; i++) {
568: acg.cg_btot[i] = 0;
569: for (j = 0; j < NRPOS; j++)
570: acg.cg_b[i][j] = 0;
571: }
572: if (cylno == 0) {
573: /*
574: * reserve space for summary info and Boot block
575: */
576: dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
577: for (d = 0; d < dlower; d += sblock.fs_frag)
578: clrblock(&sblock, acg.cg_free, d/sblock.fs_frag);
579: } else {
580: for (d = 0; d < dlower; d += sblock.fs_frag) {
581: setblock(&sblock, acg.cg_free, d/sblock.fs_frag);
582: acg.cg_cs.cs_nbfree++;
583: acg.cg_btot[cbtocylno(&sblock, d)]++;
584: acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]++;
585: }
586: sblock.fs_dsize += dlower;
587: }
588: sblock.fs_dsize += acg.cg_ndblk - dupper;
589: for (; d < dupper; d += sblock.fs_frag)
590: clrblock(&sblock, acg.cg_free, d/sblock.fs_frag);
591: if (d > dupper) {
592: acg.cg_frsum[d - dupper]++;
593: for (i = d - 1; i >= dupper; i--) {
594: setbit(acg.cg_free, i);
595: acg.cg_cs.cs_nffree++;
596: }
597: }
598: while ((d + sblock.fs_frag) <= dmax - cbase) {
599: setblock(&sblock, acg.cg_free, d/sblock.fs_frag);
600: acg.cg_cs.cs_nbfree++;
601: acg.cg_btot[cbtocylno(&sblock, d)]++;
602: acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]++;
603: d += sblock.fs_frag;
604: }
605: if (d < dmax - cbase) {
606: acg.cg_frsum[dmax - cbase - d]++;
607: for (; d < dmax - cbase; d++) {
608: setbit(acg.cg_free, d);
609: acg.cg_cs.cs_nffree++;
610: }
611: for (; d % sblock.fs_frag != 0; d++)
612: clrbit(acg.cg_free, d);
613: }
614: for (d /= sblock.fs_frag; d < MAXBPG(&sblock); d ++)
615: clrblock(&sblock, acg.cg_free, d);
616: sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir;
617: sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree;
618: sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
619: sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree;
620: *cs = acg.cg_cs;
621: wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)),
622: sblock.fs_bsize, (char *)&acg);
623: }
624:
625: /*
626: * initialize the file system
627: */
628: struct inode node;
629:
630: #ifdef LOSTDIR
631: #define PREDEFDIR 3
632: #else
633: #define PREDEFDIR 2
634: #endif
635:
636: struct direct root_dir[] = {
637: { ROOTINO, sizeof(struct direct), 1, "." },
638: { ROOTINO, sizeof(struct direct), 2, ".." },
639: #ifdef LOSTDIR
640: { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" },
641: #endif
642: };
643: #ifdef LOSTDIR
644: struct direct lost_found_dir[] = {
645: { LOSTFOUNDINO, sizeof(struct direct), 1, "." },
646: { ROOTINO, sizeof(struct direct), 2, ".." },
647: { 0, DIRBLKSIZ, 0, 0 },
648: };
649: #endif
650: char buf[MAXBSIZE];
651:
652: fsinit()
653: {
654: int i;
655:
656: /*
657: * initialize the node
658: */
659: node.i_atime = utime;
660: node.i_mtime = utime;
661: node.i_ctime = utime;
662: #ifdef LOSTDIR
663: /*
664: * create the lost+found directory
665: */
666: (void)makedir(lost_found_dir, 2);
667: for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ)
668: bcopy(&lost_found_dir[2], &buf[i], DIRSIZ(&lost_found_dir[2]));
669: node.i_number = LOSTFOUNDINO;
670: node.i_mode = IFDIR | UMASK;
671: node.i_nlink = 2;
672: node.i_size = sblock.fs_bsize;
673: node.i_db[0] = alloc(node.i_size, node.i_mode);
674: node.i_blocks = btodb(fragroundup(&sblock, node.i_size));
675: wtfs(fsbtodb(&sblock, node.i_db[0]), node.i_size, buf);
676: iput(&node);
677: #endif
678: /*
679: * create the root directory
680: */
681: node.i_number = ROOTINO;
682: node.i_mode = IFDIR | UMASK;
683: node.i_nlink = PREDEFDIR;
684: node.i_size = makedir(root_dir, PREDEFDIR);
685: node.i_db[0] = alloc(sblock.fs_fsize, node.i_mode);
686: node.i_blocks = btodb(fragroundup(&sblock, node.i_size));
687: wtfs(fsbtodb(&sblock, node.i_db[0]), sblock.fs_fsize, buf);
688: iput(&node);
689: }
690:
691: /*
692: * construct a set of directory entries in "buf".
693: * return size of directory.
694: */
695: makedir(protodir, entries)
696: register struct direct *protodir;
697: int entries;
698: {
699: char *cp;
700: int i, spcleft;
701:
702: spcleft = DIRBLKSIZ;
703: for (cp = buf, i = 0; i < entries - 1; i++) {
704: protodir[i].d_reclen = DIRSIZ(&protodir[i]);
705: bcopy(&protodir[i], cp, protodir[i].d_reclen);
706: cp += protodir[i].d_reclen;
707: spcleft -= protodir[i].d_reclen;
708: }
709: protodir[i].d_reclen = spcleft;
710: bcopy(&protodir[i], cp, DIRSIZ(&protodir[i]));
711: return (DIRBLKSIZ);
712: }
713:
714: /*
715: * allocate a block or frag
716: */
717: daddr_t
718: alloc(size, mode)
719: int size;
720: int mode;
721: {
722: int i, frag;
723: daddr_t d;
724:
725: rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
726: (char *)&acg);
727: if (acg.cg_magic != CG_MAGIC) {
728: printf("cg 0: bad magic number\n");
729: return (0);
730: }
731: if (acg.cg_cs.cs_nbfree == 0) {
732: printf("first cylinder group ran out of space\n");
733: return (0);
734: }
735: for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag)
736: if (isblock(&sblock, acg.cg_free, d / sblock.fs_frag))
737: goto goth;
738: printf("internal error: can't find block in cyl 0\n");
739: return (0);
740: goth:
741: clrblock(&sblock, acg.cg_free, d / sblock.fs_frag);
742: acg.cg_cs.cs_nbfree--;
743: sblock.fs_cstotal.cs_nbfree--;
744: fscs[0].cs_nbfree--;
745: if (mode & IFDIR) {
746: acg.cg_cs.cs_ndir++;
747: sblock.fs_cstotal.cs_ndir++;
748: fscs[0].cs_ndir++;
749: }
750: acg.cg_btot[cbtocylno(&sblock, d)]--;
751: acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]--;
752: if (size != sblock.fs_bsize) {
753: frag = howmany(size, sblock.fs_fsize);
754: fscs[0].cs_nffree += sblock.fs_frag - frag;
755: sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag;
756: acg.cg_cs.cs_nffree += sblock.fs_frag - frag;
757: acg.cg_frsum[sblock.fs_frag - frag]++;
758: for (i = frag; i < sblock.fs_frag; i++)
759: setbit(acg.cg_free, d + i);
760: }
761: wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
762: (char *)&acg);
763: return (d);
764: }
765:
766: /*
767: * Allocate an inode on the disk
768: */
769: iput(ip)
770: register struct inode *ip;
771: {
772: struct dinode buf[MAXINOPB];
773: daddr_t d;
774: int c;
775:
776: c = itog(&sblock, ip->i_number);
777: rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
778: (char *)&acg);
779: if (acg.cg_magic != CG_MAGIC) {
780: printf("cg 0: bad magic number\n");
781: exit(1);
782: }
783: acg.cg_cs.cs_nifree--;
784: setbit(acg.cg_iused, ip->i_number);
785: wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
786: (char *)&acg);
787: sblock.fs_cstotal.cs_nifree--;
788: fscs[0].cs_nifree--;
789: if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) {
790: printf("fsinit: inode value out of range (%d).\n",
791: ip->i_number);
792: exit(1);
793: }
794: d = fsbtodb(&sblock, itod(&sblock, ip->i_number));
795: rdfs(d, sblock.fs_bsize, buf);
796: buf[itoo(&sblock, ip->i_number)].di_ic = ip->i_ic;
797: wtfs(d, sblock.fs_bsize, buf);
798: }
799:
800: /*
801: * read a block from the file system
802: */
803: rdfs(bno, size, bf)
804: daddr_t bno;
805: int size;
806: char *bf;
807: {
808: int n;
809:
810: if (lseek(fsi, bno * sectorsize, 0) < 0) {
811: printf("seek error: %ld\n", bno);
812: perror("rdfs");
813: exit(1);
814: }
815: n = read(fsi, bf, size);
816: if(n != size) {
817: printf("read error: %ld\n", bno);
818: perror("rdfs");
819: exit(1);
820: }
821: }
822:
823: /*
824: * write a block to the file system
825: */
826: wtfs(bno, size, bf)
827: daddr_t bno;
828: int size;
829: char *bf;
830: {
831: int n;
832:
833: if (Nflag)
834: return;
835: if (lseek(fso, bno * sectorsize, 0) < 0) {
836: printf("seek error: %ld\n", bno);
837: perror("wtfs");
838: exit(1);
839: }
840: n = write(fso, bf, size);
841: if(n != size) {
842: printf("write error: %D\n", bno);
843: perror("wtfs");
844: exit(1);
845: }
846: }
847:
848: /*
849: * check if a block is available
850: */
851: isblock(fs, cp, h)
852: struct fs *fs;
853: unsigned char *cp;
854: int h;
855: {
856: unsigned char mask;
857:
858: switch (fs->fs_frag) {
859: case 8:
860: return (cp[h] == 0xff);
861: case 4:
862: mask = 0x0f << ((h & 0x1) << 2);
863: return ((cp[h >> 1] & mask) == mask);
864: case 2:
865: mask = 0x03 << ((h & 0x3) << 1);
866: return ((cp[h >> 2] & mask) == mask);
867: case 1:
868: mask = 0x01 << (h & 0x7);
869: return ((cp[h >> 3] & mask) == mask);
870: default:
871: #ifdef STANDALONE
872: printf("isblock bad fs_frag %d\n", fs->fs_frag);
873: #else
874: fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
875: #endif
876: return (0);
877: }
878: }
879:
880: /*
881: * take a block out of the map
882: */
883: clrblock(fs, cp, h)
884: struct fs *fs;
885: unsigned char *cp;
886: int h;
887: {
888: switch ((fs)->fs_frag) {
889: case 8:
890: cp[h] = 0;
891: return;
892: case 4:
893: cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
894: return;
895: case 2:
896: cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
897: return;
898: case 1:
899: cp[h >> 3] &= ~(0x01 << (h & 0x7));
900: return;
901: default:
902: #ifdef STANDALONE
903: printf("clrblock bad fs_frag %d\n", fs->fs_frag);
904: #else
905: fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag);
906: #endif
907: return;
908: }
909: }
910:
911: /*
912: * put a block into the map
913: */
914: setblock(fs, cp, h)
915: struct fs *fs;
916: unsigned char *cp;
917: int h;
918: {
919: switch (fs->fs_frag) {
920: case 8:
921: cp[h] = 0xff;
922: return;
923: case 4:
924: cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
925: return;
926: case 2:
927: cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
928: return;
929: case 1:
930: cp[h >> 3] |= (0x01 << (h & 0x7));
931: return;
932: default:
933: #ifdef STANDALONE
934: printf("setblock bad fs_frag %d\n", fs->fs_frag);
935: #else
936: fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag);
937: #endif
938: return;
939: }
940: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.