merge into the kernel!
[unix-history] / usr / src / sbin / newfs / mkfs.c
CommitLineData
3352e84a 1static char *sccsid = "@(#)mkfs.c 1.19 (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
d746d022
KM
9#ifndef STANDALONE
10#include <stdio.h>
11#include <a.out.h>
12#endif
13
14#include "../h/param.h"
d746d022
KM
15#include "../h/inode.h"
16#include "../h/fs.h"
052efd62 17#include <ndir.h>
d746d022 18
2fd3d252 19#define UMASK 0755
c312eebd 20#define MAXINOPB (MAXBSIZE / sizeof(struct dinode))
2fd3d252 21#define POWEROF2(num) (((num) & ((num) - 1)) == 0)
d746d022
KM
22
23union {
24 struct fs fs;
b6407c9d 25 char pad[MAXBSIZE];
d746d022
KM
26} fsun;
27#define sblock fsun.fs
28struct csum *fscs;
29
30union {
31 struct cg cg;
b6407c9d 32 char pad[MAXBSIZE];
d746d022
KM
33} cgun;
34#define acg cgun.cg
35
2fd3d252
KM
36struct dinode zino[MAXIPG];
37
d746d022 38char *fsys;
2fd3d252
KM
39time_t utime;
40int fsi;
41int fso;
d746d022
KM
42daddr_t alloc();
43
d746d022 44main(argc, argv)
b6407c9d
KM
45 int argc;
46 char *argv[];
d746d022 47{
aca50d72 48 long cylno, rpos, blk, i, inos, fssize;
d746d022 49
d746d022 50#ifndef STANDALONE
2fd3d252 51 argc--, argv++;
d746d022 52 time(&utime);
2fd3d252
KM
53 if (argc < 2) {
54 printf("usage: mkfs special size [ nsect ntrak bsize fsize cpg ]\n");
d746d022
KM
55 exit(1);
56 }
57 fsys = argv[0];
2fd3d252
KM
58 fssize = atoi(argv[1]);
59 fso = creat(fsys, 0666);
60 if(fso < 0) {
61 printf("%s: cannot create\n", fsys);
62 exit(1);
63 }
64 fsi = open(fsys, 0);
65 if(fsi < 0) {
66 printf("%s: cannot open\n", fsys);
67 exit(1);
68 }
d746d022
KM
69#else
70 {
71 static char protos[60];
2fd3d252 72 char fsbuf[100];
d746d022
KM
73
74 printf("file sys size: ");
75 gets(protos);
2fd3d252 76 fssize = atoi(protos);
d746d022
KM
77 do {
78 printf("file system: ");
79 gets(fsbuf);
80 fso = open(fsbuf, 1);
81 fsi = open(fsbuf, 0);
82 } while (fso < 0 || fsi < 0);
83 }
d746d022 84 argc = 0;
2fd3d252
KM
85#endif
86 if (fssize <= 0)
87 printf("preposterous size %d\n", fssize), exit(1);
88 /*
89 * collect and verify the sector and track info
90 */
91 if (argc > 2)
92 sblock.fs_nsect = atoi(argv[2]);
93 else
94 sblock.fs_nsect = DFLNSECT;
95 if (argc > 3)
96 sblock.fs_ntrak = atoi(argv[3]);
97 else
98 sblock.fs_ntrak = DFLNTRAK;
99 if (sblock.fs_ntrak <= 0)
100 printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1);
101 if (sblock.fs_nsect <= 0)
102 printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1);
103 sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect;
104 /*
105 * collect and verify the block and fragment sizes
106 */
107 if (argc > 4)
108 sblock.fs_bsize = atoi(argv[4]);
109 else
110 sblock.fs_bsize = MAXBSIZE;
111 if (argc > 5)
112 sblock.fs_fsize = atoi(argv[5]);
113 else
114 sblock.fs_fsize = MAX(sblock.fs_bsize / DESFRAG, DEV_BSIZE);
115 if (!POWEROF2(sblock.fs_bsize)) {
116 printf("block size must be a power of 2, not %d\n",
117 sblock.fs_bsize);
d746d022
KM
118 exit(1);
119 }
2fd3d252
KM
120 if (!POWEROF2(sblock.fs_fsize)) {
121 printf("fragment size must be a power of 2, not %d\n",
122 sblock.fs_fsize);
d746d022
KM
123 exit(1);
124 }
b6407c9d
KM
125 if (sblock.fs_fsize < DEV_BSIZE) {
126 printf("fragment size %d is too small, minimum is %d\n",
127 sblock.fs_fsize, DEV_BSIZE);
128 exit(1);
129 }
130 if (sblock.fs_bsize < MINBSIZE) {
131 printf("block size %d is too small, minimum is %d\n",
132 sblock.fs_bsize, MINBSIZE);
133 exit(1);
134 }
2fd3d252
KM
135 if (sblock.fs_bsize < sblock.fs_fsize) {
136 printf("block size (%d) cannot be smaller than fragment size (%d)\n",
137 sblock.fs_bsize, sblock.fs_fsize);
d746d022
KM
138 exit(1);
139 }
3352e84a
KM
140 sblock.fs_bmask = ~(sblock.fs_bsize - 1);
141 sblock.fs_fmask = ~(sblock.fs_fsize - 1);
142 for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1)
143 sblock.fs_bshift++;
144 for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1)
145 sblock.fs_fshift++;
146 sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize);
2fd3d252
KM
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);
d746d022 152 }
aca50d72
KM
153 sblock.fs_bblkno = BBLOCK;
154 sblock.fs_sblkno = SBLOCK;
155 sblock.fs_cblkno = (daddr_t)
156 roundup(howmany(BBSIZE + SBSIZE, sblock.fs_fsize), sblock.fs_frag);
157 sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag;
3aaf0f69
KM
158 for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc;
159 sblock.fs_cpc > 1 && (i & 1) == 0;
160 sblock.fs_cpc >>= 1, i >>= 1)
161 /* void */;
173a62ff
KM
162 if (sblock.fs_cpc > MAXCPG) {
163 printf("maximum block size with nsect %d and ntrak %d is %d\n",
164 sblock.fs_nsect, sblock.fs_ntrak,
165 sblock.fs_bsize / (sblock.fs_cpc / MAXCPG));
166 exit(1);
167 }
2fd3d252
KM
168 /*
169 * collect and verify the number of cylinders per group
d746d022 170 */
2fd3d252
KM
171 if (argc > 6) {
172 sblock.fs_cpg = atoi(argv[6]);
173 sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
d746d022 174 } else {
3aaf0f69 175 sblock.fs_cpg = MAX(sblock.fs_cpc, DESCPG);
2fd3d252 176 sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
173a62ff
KM
177 while (sblock.fs_fpg / sblock.fs_frag > MAXBPG(&sblock) &&
178 sblock.fs_cpg > sblock.fs_cpc) {
179 sblock.fs_cpg -= sblock.fs_cpc;
2fd3d252
KM
180 sblock.fs_fpg =
181 (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
182 }
183 }
184 if (sblock.fs_cpg < 1) {
185 printf("cylinder groups must have at least 1 cylinder\n");
186 exit(1);
187 }
188 if (sblock.fs_cpg > MAXCPG) {
189 printf("cylinder groups are limited to %d cylinders\n", MAXCPG);
190 exit(1);
d746d022 191 }
3aaf0f69
KM
192 if (sblock.fs_cpg % sblock.fs_cpc != 0) {
193 printf("cylinder groups must have a multiple of %d cylinders\n",
194 sblock.fs_cpc);
195 exit(1);
196 }
2fd3d252
KM
197 /*
198 * Now have size for file system and nsect and ntrak.
199 * Determine number of cylinders and blocks in the file system.
200 */
201 sblock.fs_size = fssize = dbtofsb(&sblock, fssize);
202 sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc;
aca50d72
KM
203 if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) {
204 printf("Warning: %d sector(s) in last cylinder unallocated\n",
205 sblock.fs_spc -
206 (fssize * NSPF(&sblock) - sblock.fs_ncyl * sblock.fs_spc));
207 sblock.fs_ncyl++;
208 }
209 if (sblock.fs_ncyl < 1) {
210 printf("file systems must have at least one cylinder\n");
2fd3d252
KM
211 exit(1);
212 }
aca50d72
KM
213 /*
214 * determine feasability/values of rotational layout tables
215 */
216 if (sblock.fs_ntrak == 1) {
217 sblock.fs_cpc = 0;
218 goto next;
219 }
aca50d72
KM
220 if (sblock.fs_spc * sblock.fs_cpc > MAXBPC * NSPB(&sblock) ||
221 sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) {
222 printf("%s %s %d %s %d.%s",
223 "Warning: insufficient space in super block for\n",
224 "rotational layout tables with nsect", sblock.fs_nsect,
225 "and ntrak", sblock.fs_ntrak,
226 "\nFile system performance may be impared.\n");
227 sblock.fs_cpc = 0;
228 goto next;
229 }
230 /*
231 * calculate the available blocks for each rotational position
232 */
233 for (cylno = 0; cylno < MAXCPG; cylno++)
234 for (rpos = 0; rpos < NRPOS; rpos++)
235 sblock.fs_postbl[cylno][rpos] = -1;
236 blk = sblock.fs_spc * sblock.fs_cpc / NSPF(&sblock);
237 for (i = 0; i < blk; i += sblock.fs_frag)
238 /* void */;
239 for (i -= sblock.fs_frag; i >= 0; i -= sblock.fs_frag) {
240 cylno = cbtocylno(&sblock, i);
241 rpos = cbtorpos(&sblock, i);
242 blk = i / sblock.fs_frag;
243 if (sblock.fs_postbl[cylno][rpos] == -1)
244 sblock.fs_rotbl[blk] = 0;
245 else
246 sblock.fs_rotbl[blk] =
247 sblock.fs_postbl[cylno][rpos] - blk;
248 sblock.fs_postbl[cylno][rpos] = blk;
249 }
250next:
2fd3d252
KM
251 /*
252 * Validate specified/determined cpg.
253 */
254 if (sblock.fs_spc > MAXBPG(&sblock) * NSPB(&sblock)) {
255 printf("too many sectors per cylinder (%d sectors)\n",
256 sblock.fs_spc);
257 while(sblock.fs_spc > MAXBPG(&sblock) * NSPB(&sblock)) {
258 sblock.fs_bsize <<= 1;
259 if (sblock.fs_frag < MAXFRAG)
260 sblock.fs_frag <<= 1;
261 else
262 sblock.fs_fsize <<= 1;
263 }
264 printf("nsect %d, and ntrak %d, requires block size of %d,\n",
265 sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_bsize);
266 printf("\tand fragment size of %d\n", sblock.fs_fsize);
267 exit(1);
268 }
269 if (sblock.fs_fpg > MAXBPG(&sblock) * sblock.fs_frag) {
270 printf("cylinder group too large (%d cylinders); ",
271 sblock.fs_cpg);
aca50d72 272 printf("max: %d cylinders per group\n",
2fd3d252
KM
273 MAXBPG(&sblock) * sblock.fs_frag /
274 (sblock.fs_fpg / sblock.fs_cpg));
275 exit(1);
276 }
3352e84a
KM
277 sblock.fs_cgsize = fragroundup(&sblock,
278 sizeof(struct cg) + howmany(sblock.fs_fpg, NBBY));
d746d022
KM
279 /*
280 * Compute/validate number of cylinder groups.
281 */
282 sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg;
283 if (sblock.fs_ncyl % sblock.fs_cpg)
284 sblock.fs_ncg++;
2fd3d252 285 if ((sblock.fs_spc * sblock.fs_cpg) % NSPF(&sblock)) {
d746d022
KM
286 printf("mkfs: nsect %d, ntrak %d, cpg %d is not tolerable\n",
287 sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_cpg);
288 printf("as this would would have cyl groups whose size\n");
b6407c9d 289 printf("is not a multiple of %d; choke!\n", sblock.fs_fsize);
d746d022
KM
290 exit(1);
291 }
d746d022
KM
292 /*
293 * Compute number of inode blocks per cylinder group.
294 * Start with one inode per NBPI bytes; adjust as necessary.
295 */
aca50d72
KM
296 i = sblock.fs_iblkno + MAXIPG / INOPF(&sblock);
297 inos = (fssize - sblock.fs_ncg * i) * sblock.fs_fsize /
298 MAX(NBPI, sblock.fs_fsize) / INOPB(&sblock);
2fd3d252
KM
299 if (inos <= 0)
300 inos = 1;
301 sblock.fs_ipg = ((inos / sblock.fs_ncg) + 1) * INOPB(&sblock);
d746d022
KM
302 if (sblock.fs_ipg > MAXIPG)
303 sblock.fs_ipg = MAXIPG;
aca50d72 304 sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock);
6994bf5d 305 if (cgdmin(&sblock, 0) >= sblock.fs_fpg) {
d746d022 306 printf("inode blocks/cyl group (%d) >= data blocks (%d)\n",
6994bf5d 307 cgdmin(&sblock, 0) / sblock.fs_frag,
b6407c9d 308 sblock.fs_fpg / sblock.fs_frag);
2fd3d252 309 printf("number of cylinder per cylinder group must be increased\n");
b6407c9d
KM
310 exit(1);
311 }
2fd3d252
KM
312 /*
313 * fill in remaining fields of the super block
314 */
6994bf5d 315 sblock.fs_csaddr = cgdmin(&sblock, 0);
b6407c9d 316 sblock.fs_cssize = sblock.fs_ncg * sizeof(struct csum);
aca50d72 317 fscs = (struct csum *)
3352e84a 318 calloc(1, blkroundup(&sblock, sblock.fs_cssize));
aca50d72 319 sblock.fs_magic = FS_MAGIC;
2fd3d252
KM
320 sblock.fs_rotdelay = ROTDELAY;
321 sblock.fs_minfree = MINFREE;
aca50d72 322 sblock.fs_rps = HZ; /* assume disk speed == HZ */
2fd3d252
KM
323 sblock.fs_cgrotor = 0;
324 sblock.fs_cstotal.cs_ndir = 0;
325 sblock.fs_cstotal.cs_nbfree = 0;
326 sblock.fs_cstotal.cs_nifree = 0;
327 sblock.fs_cstotal.cs_nffree = 0;
d746d022
KM
328 sblock.fs_fmod = 0;
329 sblock.fs_ronly = 0;
d746d022 330 /*
2fd3d252 331 * Dump out summary information about file system.
d746d022
KM
332 */
333 printf("%s:\t%d sectors in %d cylinders of %d tracks, %d sectors\n",
2fd3d252 334 fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl,
b6407c9d 335 sblock.fs_ntrak, sblock.fs_nsect);
d746d022 336 printf("\t%.1fMb in %d cyl groups (%d c/g, %.2fMb/g, %d i/g)\n",
b6407c9d
KM
337 (float)sblock.fs_size * sblock.fs_fsize * 1e-6, sblock.fs_ncg,
338 sblock.fs_cpg, (float)sblock.fs_fpg * sblock.fs_fsize * 1e-6,
339 sblock.fs_ipg);
d746d022
KM
340 /*
341 * Now build the cylinders group blocks and
2fd3d252 342 * then print out indices of cylinder groups.
d746d022 343 */
aca50d72
KM
344 for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
345 initcg(cylno);
b6407c9d 346 if (sblock.fs_ncg == 1)
aca50d72 347 printf("Warning: no super-block backups with only one cylinder group\n");
b6407c9d
KM
348 else
349 printf("\tsuper-block backups (for fsck -b#) at %d+k*%d (%d .. %d)\n",
6994bf5d
KM
350 SBLOCK, cgsblock(&sblock, 1) - SBLOCK, cgsblock(&sblock, 1),
351 cgsblock(&sblock, sblock.fs_ncg - 1));
d746d022 352 /*
2fd3d252 353 * Now construct the initial file system,
d746d022
KM
354 * then write out the super-block.
355 */
2fd3d252 356 fsinit();
d746d022 357 sblock.fs_time = utime;
2fd3d252 358 wtfs(SBLOCK, SBSIZE, (char *)&sblock);
b6407c9d 359 for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize)
3352e84a 360 wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)),
b6407c9d 361 sblock.fs_bsize, ((char *)fscs) + i);
2fd3d252
KM
362 /*
363 * Write out the duplicate super blocks
364 */
aca50d72 365 for (cylno = 1; cylno < sblock.fs_ncg; cylno++)
6994bf5d 366 wtfs(cgsblock(&sblock, cylno), SBSIZE, (char *)&sblock);
d746d022 367#ifndef STANDALONE
2fd3d252 368 exit(0);
d746d022
KM
369#endif
370}
371
372/*
373 * Initialize a cylinder group.
374 */
aca50d72
KM
375initcg(cylno)
376 int cylno;
d746d022
KM
377{
378 daddr_t cbase, d, dmin, dmax;
379 long i, j, s;
380 register struct csum *cs;
381
382 /*
383 * Determine block bounds for cylinder group.
384 * Allow space for super block summary information in first
385 * cylinder group.
386 */
6994bf5d 387 cbase = cgbase(&sblock, cylno);
d746d022
KM
388 dmax = cbase + sblock.fs_fpg;
389 if (dmax > sblock.fs_size)
390 dmax = sblock.fs_size;
aca50d72 391 dmin = sblock.fs_dblkno;
d746d022 392 d = cbase;
aca50d72 393 cs = fscs + cylno;
d746d022
KM
394 acg.cg_time = utime;
395 acg.cg_magic = CG_MAGIC;
aca50d72 396 acg.cg_cgx = cylno;
d746d022
KM
397 acg.cg_ncyl = sblock.fs_cpg;
398 acg.cg_niblk = sblock.fs_ipg;
399 acg.cg_ndblk = dmax - cbase;
0947395d
KM
400 acg.cg_cs.cs_ndir = 0;
401 acg.cg_cs.cs_nffree = 0;
402 acg.cg_cs.cs_nbfree = 0;
403 acg.cg_cs.cs_nifree = 0;
f3c028b7
KM
404 acg.cg_rotor = dmin;
405 acg.cg_frotor = dmin;
92ea6158 406 acg.cg_irotor = 0;
b6407c9d 407 for (i = 0; i < sblock.fs_frag; i++) {
f3c028b7
KM
408 acg.cg_frsum[i] = 0;
409 }
410 for (i = 0; i < sblock.fs_ipg; ) {
b6407c9d 411 for (j = INOPB(&sblock); j > 0; j--) {
d746d022
KM
412 clrbit(acg.cg_iused, i);
413 i++;
414 }
b6407c9d 415 acg.cg_cs.cs_nifree += INOPB(&sblock);
d746d022 416 }
aca50d72 417 if (cylno == 0)
2fd3d252
KM
418 for (i = 0; i < ROOTINO; i++) {
419 setbit(acg.cg_iused, i);
420 acg.cg_cs.cs_nifree--;
421 }
d746d022
KM
422 while (i < MAXIPG) {
423 clrbit(acg.cg_iused, i);
424 i++;
425 }
6994bf5d 426 lseek(fso, fsbtodb(&sblock, cgimin(&sblock, cylno)) * DEV_BSIZE, 0);
d746d022
KM
427 if (write(fso, (char *)zino, sblock.fs_ipg * sizeof (struct dinode)) !=
428 sblock.fs_ipg * sizeof (struct dinode))
3352e84a 429 printf("write error %D\n", numfrags(&sblock, tell(fso)));
43f6367c
KM
430 for (i = 0; i < MAXCPG; i++) {
431 acg.cg_btot[i] = 0;
d746d022
KM
432 for (j = 0; j < NRPOS; j++)
433 acg.cg_b[i][j] = 0;
43f6367c 434 }
aca50d72 435 if (cylno == 0) {
b6407c9d
KM
436 dmin += howmany(sblock.fs_cssize, sblock.fs_bsize) *
437 sblock.fs_frag;
d746d022 438 }
b6407c9d
KM
439 for (d = 0; d < dmin; d += sblock.fs_frag)
440 clrblock(&sblock, acg.cg_free, d/sblock.fs_frag);
441 while ((d+sblock.fs_frag) <= dmax - cbase) {
442 setblock(&sblock, acg.cg_free, d/sblock.fs_frag);
0947395d 443 acg.cg_cs.cs_nbfree++;
43f6367c 444 acg.cg_btot[cbtocylno(&sblock, d)]++;
aca50d72 445 acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]++;
b6407c9d 446 d += sblock.fs_frag;
d746d022
KM
447 }
448 if (d < dmax - cbase)
aca50d72 449 acg.cg_frsum[dmax - cbase - d]++;
56d45dcd
KM
450 for (; d < dmax - cbase; d++) {
451 setbit(acg.cg_free, d);
0947395d 452 acg.cg_cs.cs_nffree++;
56d45dcd 453 }
b6407c9d 454 for (; d < MAXBPG(&sblock); d++)
d746d022 455 clrbit(acg.cg_free, d);
0947395d
KM
456 sblock.fs_dsize += acg.cg_ndblk - dmin;
457 sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir;
458 sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree;
459 sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
460 sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree;
461 *cs = acg.cg_cs;
6994bf5d 462 wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)),
b6407c9d 463 sblock.fs_bsize, (char *)&acg);
d746d022
KM
464}
465
2fd3d252
KM
466/*
467 * initialize the file system
468 */
469struct inode node;
470#define PREDEFDIR 3
052efd62
KM
471struct direct root_dir[] = {
472 { ROOTINO, sizeof(struct direct), 1, "." },
473 { ROOTINO, sizeof(struct direct), 2, ".." },
474 { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" },
2fd3d252 475};
052efd62
KM
476struct direct lost_found_dir[] = {
477 { LOSTFOUNDINO, sizeof(struct direct), 1, "." },
478 { ROOTINO, sizeof(struct direct), 2, ".." },
479 { 0, DIRBLKSIZ, 0, 0 },
2fd3d252 480};
052efd62 481char buf[MAXBSIZE];
2fd3d252
KM
482
483fsinit()
d746d022 484{
052efd62
KM
485 int i;
486
d746d022 487 /*
2fd3d252 488 * initialize the node
d746d022 489 */
2fd3d252
KM
490 node.i_atime = utime;
491 node.i_mtime = utime;
492 node.i_ctime = utime;
d746d022 493 /*
2fd3d252 494 * create the lost+found directory
d746d022 495 */
052efd62
KM
496 (void)makedir(lost_found_dir, 2);
497 for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ)
498 bcopy(&lost_found_dir[2], &buf[i], DIRSIZ(&lost_found_dir[2]));
2fd3d252
KM
499 node.i_number = LOSTFOUNDINO;
500 node.i_mode = IFDIR | UMASK;
501 node.i_nlink = 2;
502 node.i_size = sblock.fs_bsize;
503 node.i_db[0] = alloc(node.i_size, node.i_mode);
052efd62 504 wtfs(fsbtodb(&sblock, node.i_db[0]), node.i_size, buf);
2fd3d252
KM
505 iput(&node);
506 /*
507 * create the root directory
508 */
509 node.i_number = ROOTINO;
510 node.i_mode = IFDIR | UMASK;
511 node.i_nlink = PREDEFDIR;
052efd62 512 node.i_size = makedir(root_dir, PREDEFDIR);
2fd3d252 513 node.i_db[0] = alloc(sblock.fs_fsize, node.i_mode);
052efd62 514 wtfs(fsbtodb(&sblock, node.i_db[0]), sblock.fs_fsize, buf);
2fd3d252 515 iput(&node);
d746d022
KM
516}
517
052efd62
KM
518/*
519 * construct a set of directory entries in "buf".
520 * return size of directory.
521 */
522makedir(protodir, entries)
523 register struct direct *protodir;
524 int entries;
525{
526 char *cp;
527 int i, spcleft;
528
529 spcleft = DIRBLKSIZ;
530 for (cp = buf, i = 0; i < entries - 1; i++) {
531 protodir[i].d_reclen = DIRSIZ(&protodir[i]);
532 bcopy(&protodir[i], cp, protodir[i].d_reclen);
533 cp += protodir[i].d_reclen;
534 spcleft -= protodir[i].d_reclen;
535 }
536 protodir[i].d_reclen = spcleft;
537 bcopy(&protodir[i], cp, DIRSIZ(&protodir[i]));
538 cp += DIRSIZ(&protodir[i]);
539 return (cp - buf);
540}
541
2fd3d252
KM
542/*
543 * allocate a block or frag
544 */
d746d022 545daddr_t
07670f7d
KM
546alloc(size, mode)
547 int size;
548 int mode;
d746d022 549{
aca50d72 550 int i, frag;
d746d022
KM
551 daddr_t d;
552
3352e84a
KM
553 rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
554 (char *)&acg);
0947395d 555 if (acg.cg_cs.cs_nbfree == 0) {
d746d022
KM
556 printf("first cylinder group ran out of space\n");
557 return (0);
558 }
b6407c9d
KM
559 for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag)
560 if (isblock(&sblock, acg.cg_free, d / sblock.fs_frag))
d746d022
KM
561 goto goth;
562 printf("internal error: can't find block in cyl 0\n");
563 return (0);
564goth:
b6407c9d 565 clrblock(&sblock, acg.cg_free, d / sblock.fs_frag);
0947395d
KM
566 acg.cg_cs.cs_nbfree--;
567 sblock.fs_cstotal.cs_nbfree--;
d746d022 568 fscs[0].cs_nbfree--;
07670f7d 569 if (mode & IFDIR) {
0947395d
KM
570 acg.cg_cs.cs_ndir++;
571 sblock.fs_cstotal.cs_ndir++;
07670f7d
KM
572 fscs[0].cs_ndir++;
573 }
43f6367c 574 acg.cg_btot[cbtocylno(&sblock, d)]--;
aca50d72 575 acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]--;
b6407c9d
KM
576 if (size != sblock.fs_bsize) {
577 frag = howmany(size, sblock.fs_fsize);
578 fscs[0].cs_nffree += sblock.fs_frag - frag;
579 sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag;
580 acg.cg_cs.cs_nffree += sblock.fs_frag - frag;
581 acg.cg_frsum[sblock.fs_frag - frag]++;
582 for (i = frag; i < sblock.fs_frag; i++)
d746d022
KM
583 setbit(acg.cg_free, d+i);
584 }
3352e84a
KM
585 wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
586 (char *)&acg);
d746d022
KM
587 return (d);
588}
589
2fd3d252
KM
590/*
591 * Allocate an inode on the disk
592 */
593iput(ip)
594 register struct inode *ip;
d746d022 595{
2fd3d252 596 struct dinode buf[MAXINOPB];
d746d022 597 daddr_t d;
2fd3d252 598 int c;
d746d022 599
6994bf5d 600 c = itog(&sblock, ip->i_number);
3352e84a
KM
601 rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
602 (char *)&acg);
0947395d 603 acg.cg_cs.cs_nifree--;
d746d022 604 setbit(acg.cg_iused, ip->i_number);
3352e84a
KM
605 wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
606 (char *)&acg);
0947395d 607 sblock.fs_cstotal.cs_nifree--;
d746d022 608 fscs[0].cs_nifree--;
d746d022 609 if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) {
2fd3d252
KM
610 printf("fsinit: inode value out of range (%d).\n",
611 ip->i_number);
612 exit(1);
d746d022 613 }
6994bf5d 614 d = fsbtodb(&sblock, itod(&sblock, ip->i_number));
2fd3d252 615 rdfs(d, sblock.fs_bsize, buf);
6994bf5d 616 buf[itoo(&sblock, ip->i_number)].di_ic = ip->i_ic;
2fd3d252
KM
617 wtfs(d, sblock.fs_bsize, buf);
618}
619
620/*
621 * read a block from the file system
622 */
623rdfs(bno, size, bf)
624 daddr_t bno;
625 int size;
626 char *bf;
627{
628 int n;
629
c312eebd
KM
630 if (lseek(fsi, bno * DEV_BSIZE, 0) < 0) {
631 printf("seek error: %ld\n", bno);
632 perror("rdfs");
633 exit(1);
634 }
2fd3d252
KM
635 n = read(fsi, bf, size);
636 if(n != size) {
637 printf("read error: %ld\n", bno);
c312eebd 638 perror("rdfs");
2fd3d252 639 exit(1);
b6407c9d 640 }
b6407c9d
KM
641}
642
643/*
2fd3d252 644 * write a block to the file system
b6407c9d 645 */
2fd3d252
KM
646wtfs(bno, size, bf)
647 daddr_t bno;
648 int size;
649 char *bf;
650{
651 int n;
652
2fd3d252 653 lseek(fso, bno * DEV_BSIZE, 0);
c312eebd
KM
654 if (lseek(fso, bno * DEV_BSIZE, 0) < 0) {
655 printf("seek error: %ld\n", bno);
656 perror("wtfs");
657 exit(1);
658 }
2fd3d252
KM
659 n = write(fso, bf, size);
660 if(n != size) {
661 printf("write error: %D\n", bno);
c312eebd 662 perror("wtfs");
2fd3d252
KM
663 exit(1);
664 }
665}
b6407c9d 666
052efd62
KM
667/*
668 * copy a block
669 */
670bcopy(from, to, size)
671 char *from, *to;
672 int size;
673{
674 asm(" movc3 12(ap),*4(ap),*8(ap)");
675}
676
2fd3d252
KM
677/*
678 * check if a block is available
679 */
b6407c9d
KM
680isblock(fs, cp, h)
681 struct fs *fs;
682 unsigned char *cp;
683 int h;
684{
685 unsigned char mask;
686
687 switch (fs->fs_frag) {
688 case 8:
689 return (cp[h] == 0xff);
690 case 4:
691 mask = 0x0f << ((h & 0x1) << 2);
692 return ((cp[h >> 1] & mask) == mask);
693 case 2:
694 mask = 0x03 << ((h & 0x3) << 1);
695 return ((cp[h >> 2] & mask) == mask);
696 case 1:
697 mask = 0x01 << (h & 0x7);
698 return ((cp[h >> 3] & mask) == mask);
699 default:
700 fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
701 return;
702 }
703}
704
2fd3d252
KM
705/*
706 * take a block out of the map
707 */
b6407c9d
KM
708clrblock(fs, cp, h)
709 struct fs *fs;
710 unsigned char *cp;
711 int h;
712{
713 switch ((fs)->fs_frag) {
714 case 8:
715 cp[h] = 0;
716 return;
717 case 4:
718 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
719 return;
720 case 2:
721 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
722 return;
723 case 1:
724 cp[h >> 3] &= ~(0x01 << (h & 0x7));
725 return;
726 default:
727 fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag);
728 return;
729 }
730}
731
2fd3d252
KM
732/*
733 * put a block into the map
734 */
b6407c9d
KM
735setblock(fs, cp, h)
736 struct fs *fs;
737 unsigned char *cp;
738 int h;
739{
740 switch (fs->fs_frag) {
741 case 8:
742 cp[h] = 0xff;
743 return;
744 case 4:
745 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
746 return;
747 case 2:
748 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
749 return;
750 case 1:
751 cp[h >> 3] |= (0x01 << (h & 0x7));
752 return;
753 default:
754 fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag);
755 return;
d746d022 756 }
d746d022 757}