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