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