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