mkfs.c revision 1.8 1 /* $NetBSD: mkfs.c,v 1.8 2002/01/26 13:22:17 lukem Exp $ */
2 /* From NetBSD: mkfs.c,v 1.59 2001/12/31 07:07:58 lukem Exp $ */
3
4 /*
5 * Copyright (c) 1980, 1989, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37 #include <sys/cdefs.h>
38 #ifndef lint
39 #if 0
40 static char sccsid[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95";
41 #else
42 __RCSID("$NetBSD: mkfs.c,v 1.8 2002/01/26 13:22:17 lukem Exp $");
43 #endif
44 #endif /* not lint */
45
46 #include <sys/param.h>
47 #include <sys/time.h>
48 #include <sys/resource.h>
49
50 #include <err.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <unistd.h>
55
56 #include "makefs.h"
57
58 #include <ufs/ufs/dinode.h>
59 #include <ufs/ufs/dir.h>
60 #include <ufs/ufs/ufs_bswap.h>
61 #include <ufs/ffs/fs.h>
62
63 #include "ffs/ufs_inode.h"
64 #include "ffs/ffs_extern.h"
65 #include "ffs/newfs_extern.h"
66
67 static void initcg(int, time_t, const fsinfo_t *);
68 static int32_t calcipg(int32_t, int32_t, off_t *);
69 static void swap_cg(struct cg *, struct cg *);
70
71 static int count_digits(int);
72
73 /*
74 * make file system for cylinder-group style file systems
75 */
76
77 /*
78 * We limit the size of the inode map to be no more than a
79 * third of the cylinder group space, since we must leave at
80 * least an equal amount of space for the block map.
81 *
82 * N.B.: MAXIPG must be a multiple of INOPB(fs).
83 */
84 #define MAXIPG(fs) roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs))
85
86 #define UMASK 0755
87 #define POWEROF2(num) (((num) & ((num) - 1)) == 0)
88
89 union {
90 struct fs fs;
91 char pad[SBSIZE];
92 } fsun;
93 #define sblock fsun.fs
94
95 union {
96 struct cg cg;
97 char pad[MAXBSIZE];
98 } cgun;
99 #define acg cgun.cg
100
101 struct dinode zino[MAXBSIZE / DINODE_SIZE];
102
103 char writebuf[MAXBSIZE];
104
105 static int Oflag; /* format as an 4.3BSD file system */
106 static int fssize; /* file system size */
107 static int ntracks; /* # tracks/cylinder */
108 static int nsectors; /* # sectors/track */
109 static int nphyssectors; /* # sectors/track including spares */
110 static int secpercyl; /* sectors per cylinder */
111 static int sectorsize; /* bytes/sector */
112 static int rpm; /* revolutions/minute of drive */
113 static int interleave; /* hardware sector interleave */
114 static int trackskew; /* sector 0 skew, per track */
115 static int fsize; /* fragment size */
116 static int bsize; /* block size */
117 static int cpg; /* cylinders/cylinder group */
118 static int cpgflg; /* cylinders/cylinder group flag was given */
119 static int minfree; /* free space threshold */
120 static int opt; /* optimization preference (space or time) */
121 static int density; /* number of bytes per inode */
122 static int maxcontig; /* max contiguous blocks to allocate */
123 static int rotdelay; /* rotational delay between blocks */
124 static int maxbpg; /* maximum blocks per file in a cyl group */
125 static int nrpos; /* # of distinguished rotational positions */
126 static int bbsize; /* boot block size */
127 static int sbsize; /* superblock size */
128 static int avgfilesize; /* expected average file size */
129 static int avgfpdir; /* expected number of files per directory */
130
131
132 struct fs *
133 ffs_mkfs(const char *fsys, const fsinfo_t *fsopts)
134 {
135 int32_t i, mincpc, mincpg, inospercg;
136 int32_t cylno, rpos, blk, j, warned = 0;
137 int32_t used, mincpgcnt, bpcg;
138 off_t usedb;
139 int32_t mapcramped, inodecramped;
140 int32_t postblsize, rotblsize, totalsbsize;
141 long long sizepb;
142 void *space;
143 int size, blks;
144 int nprintcols, printcolwidth;
145
146 Oflag = 0;
147 fssize = fsopts->size / fsopts->sectorsize;
148 ntracks = fsopts->ntracks;
149 nsectors = fsopts->nsectors;
150 nphyssectors = fsopts->nsectors; /* XXX: no trackspares */
151 secpercyl = nsectors * ntracks;
152 sectorsize = fsopts->sectorsize;
153 rpm = fsopts->rpm;
154 interleave = 1;
155 trackskew = 0;
156 fsize = fsopts->fsize;
157 bsize = fsopts->bsize;
158 cpg = fsopts->cpg;
159 cpgflg = fsopts->cpgflg;
160 minfree = fsopts->minfree;
161 opt = fsopts->optimization;
162 density = fsopts->density;
163 maxcontig = fsopts->maxcontig;
164 rotdelay = fsopts->rotdelay;
165 maxbpg = fsopts->maxbpg;
166 nrpos = fsopts->nrpos;
167 bbsize = BBSIZE;
168 sbsize = SBSIZE;
169 avgfilesize = fsopts->avgfilesize;
170 avgfpdir = fsopts->avgfpdir;
171
172 if (Oflag) {
173 sblock.fs_inodefmt = FS_42INODEFMT;
174 sblock.fs_maxsymlinklen = 0;
175 } else {
176 sblock.fs_inodefmt = FS_44INODEFMT;
177 sblock.fs_maxsymlinklen = MAXSYMLINKLEN;
178 }
179 /*
180 * Validate the given file system size.
181 * Verify that its last block can actually be accessed.
182 */
183 if (fssize <= 0)
184 printf("preposterous size %d\n", fssize), exit(13);
185 ffs_wtfs(fssize - 1, sectorsize, (char *)&sblock, fsopts);
186
187 /*
188 * collect and verify the sector and track info
189 */
190 sblock.fs_nsect = nsectors;
191 sblock.fs_ntrak = ntracks;
192 if (sblock.fs_ntrak <= 0)
193 printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(14);
194 if (sblock.fs_nsect <= 0)
195 printf("preposterous nsect %d\n", sblock.fs_nsect), exit(15);
196 /*
197 * collect and verify the filesystem density info
198 */
199 sblock.fs_avgfilesize = avgfilesize;
200 sblock.fs_avgfpdir = avgfpdir;
201 if (sblock.fs_avgfilesize <= 0)
202 printf("illegal expected average file size %d\n",
203 sblock.fs_avgfilesize), exit(14);
204 if (sblock.fs_avgfpdir <= 0)
205 printf("illegal expected number of files per directory %d\n",
206 sblock.fs_avgfpdir), exit(15);
207 /*
208 * collect and verify the block and fragment sizes
209 */
210 sblock.fs_bsize = bsize;
211 sblock.fs_fsize = fsize;
212 if (!POWEROF2(sblock.fs_bsize)) {
213 printf("block size must be a power of 2, not %d\n",
214 sblock.fs_bsize);
215 exit(16);
216 }
217 if (!POWEROF2(sblock.fs_fsize)) {
218 printf("fragment size must be a power of 2, not %d\n",
219 sblock.fs_fsize);
220 exit(17);
221 }
222 if (sblock.fs_fsize < sectorsize) {
223 printf("fragment size %d is too small, minimum is %d\n",
224 sblock.fs_fsize, sectorsize);
225 exit(18);
226 }
227 if (sblock.fs_bsize > MAXBSIZE) {
228 printf("block size %d is too large, maximum is %d\n",
229 sblock.fs_bsize, MAXBSIZE);
230 exit(19);
231 }
232 if (sblock.fs_bsize < MINBSIZE) {
233 printf("block size %d is too small, minimum is %d\n",
234 sblock.fs_bsize, MINBSIZE);
235 exit(19);
236 }
237 if (sblock.fs_bsize < sblock.fs_fsize) {
238 printf("block size (%d) cannot be smaller than fragment size (%d)\n",
239 sblock.fs_bsize, sblock.fs_fsize);
240 exit(20);
241 }
242 sblock.fs_bmask = ~(sblock.fs_bsize - 1);
243 sblock.fs_fmask = ~(sblock.fs_fsize - 1);
244 sblock.fs_qbmask = ~sblock.fs_bmask;
245 sblock.fs_qfmask = ~sblock.fs_fmask;
246 for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1)
247 sblock.fs_bshift++;
248 for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1)
249 sblock.fs_fshift++;
250 sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize);
251 for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1)
252 sblock.fs_fragshift++;
253 if (sblock.fs_frag > MAXFRAG) {
254 printf("fragment size %d is too small, "
255 "minimum with block size %d is %d\n",
256 sblock.fs_fsize, sblock.fs_bsize,
257 sblock.fs_bsize / MAXFRAG);
258 exit(21);
259 }
260 sblock.fs_nrpos = nrpos;
261 sblock.fs_nindir = sblock.fs_bsize / sizeof(daddr_t);
262 sblock.fs_inopb = sblock.fs_bsize / DINODE_SIZE;
263 sblock.fs_nspf = sblock.fs_fsize / sectorsize;
264 for (sblock.fs_fsbtodb = 0, i = NSPF(&sblock); i > 1; i >>= 1)
265 sblock.fs_fsbtodb++;
266 sblock.fs_sblkno =
267 roundup(howmany(bbsize + sbsize, sblock.fs_fsize), sblock.fs_frag);
268 sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno +
269 roundup(howmany(sbsize, sblock.fs_fsize), sblock.fs_frag));
270 sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag;
271 sblock.fs_cgoffset = roundup(
272 howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag);
273 for (sblock.fs_cgmask = 0xffffffff, i = sblock.fs_ntrak; i > 1; i >>= 1)
274 sblock.fs_cgmask <<= 1;
275 if (!POWEROF2(sblock.fs_ntrak))
276 sblock.fs_cgmask <<= 1;
277 sblock.fs_maxfilesize = sblock.fs_bsize * NDADDR - 1;
278 for (sizepb = sblock.fs_bsize, i = 0; i < NIADDR; i++) {
279 sizepb *= NINDIR(&sblock);
280 sblock.fs_maxfilesize += sizepb;
281 }
282 /*
283 * Validate specified/determined secpercyl
284 * and calculate minimum cylinders per group.
285 */
286 sblock.fs_spc = secpercyl;
287 for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc;
288 sblock.fs_cpc > 1 && (i & 1) == 0;
289 sblock.fs_cpc >>= 1, i >>= 1)
290 /* void */;
291 mincpc = sblock.fs_cpc;
292 bpcg = sblock.fs_spc * sectorsize;
293 inospercg = roundup(bpcg / DINODE_SIZE, INOPB(&sblock));
294 if (inospercg > MAXIPG(&sblock))
295 inospercg = MAXIPG(&sblock);
296 used = (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock);
297 mincpgcnt = howmany(sblock.fs_cgoffset * (~sblock.fs_cgmask) + used,
298 sblock.fs_spc);
299 mincpg = roundup(mincpgcnt, mincpc);
300 /*
301 * Ensure that cylinder group with mincpg has enough space
302 * for block maps.
303 */
304 sblock.fs_cpg = mincpg;
305 sblock.fs_ipg = inospercg;
306 if (maxcontig > 1)
307 sblock.fs_contigsumsize = MIN(maxcontig, FS_MAXCONTIG);
308 mapcramped = 0;
309 while (CGSIZE(&sblock) > sblock.fs_bsize) {
310 mapcramped = 1;
311 if (sblock.fs_bsize < MAXBSIZE) {
312 sblock.fs_bsize <<= 1;
313 if ((i & 1) == 0) {
314 i >>= 1;
315 } else {
316 sblock.fs_cpc <<= 1;
317 mincpc <<= 1;
318 mincpg = roundup(mincpgcnt, mincpc);
319 sblock.fs_cpg = mincpg;
320 }
321 sblock.fs_frag <<= 1;
322 sblock.fs_fragshift += 1;
323 if (sblock.fs_frag <= MAXFRAG)
324 continue;
325 }
326 if (sblock.fs_fsize == sblock.fs_bsize) {
327 printf("There is no block size that");
328 printf(" can support this disk\n");
329 exit(22);
330 }
331 sblock.fs_frag >>= 1;
332 sblock.fs_fragshift -= 1;
333 sblock.fs_fsize <<= 1;
334 sblock.fs_nspf <<= 1;
335 }
336 /*
337 * Ensure that cylinder group with mincpg has enough space for inodes.
338 */
339 inodecramped = 0;
340 inospercg = calcipg(mincpg, bpcg, &usedb);
341 sblock.fs_ipg = inospercg;
342 while (inospercg > MAXIPG(&sblock)) {
343 inodecramped = 1;
344 if (mincpc == 1 || sblock.fs_frag == 1 ||
345 sblock.fs_bsize == MINBSIZE)
346 break;
347 printf("With a block size of %d %s %d\n", sblock.fs_bsize,
348 "minimum bytes per inode is",
349 (int)((mincpg * (off_t)bpcg - usedb)
350 / MAXIPG(&sblock) + 1));
351 sblock.fs_bsize >>= 1;
352 sblock.fs_frag >>= 1;
353 sblock.fs_fragshift -= 1;
354 mincpc >>= 1;
355 sblock.fs_cpg = roundup(mincpgcnt, mincpc);
356 if (CGSIZE(&sblock) > sblock.fs_bsize) {
357 sblock.fs_bsize <<= 1;
358 break;
359 }
360 mincpg = sblock.fs_cpg;
361 inospercg = calcipg(mincpg, bpcg, &usedb);
362 sblock.fs_ipg = inospercg;
363 }
364 if (inodecramped) {
365 if (inospercg > MAXIPG(&sblock)) {
366 printf("Minimum bytes per inode is %d\n",
367 (int)((mincpg * (off_t)bpcg - usedb)
368 / MAXIPG(&sblock) + 1));
369 } else if (!mapcramped) {
370 printf("With %d bytes per inode, ", density);
371 printf("minimum cylinders per group is %d\n", mincpg);
372 }
373 }
374 if (mapcramped) {
375 printf("With %d sectors per cylinder, ", sblock.fs_spc);
376 printf("minimum cylinders per group is %d\n", mincpg);
377 }
378 if (inodecramped || mapcramped) {
379 if (sblock.fs_bsize != bsize)
380 printf("%s to be changed from %d to %d\n",
381 "This requires the block size",
382 bsize, sblock.fs_bsize);
383 if (sblock.fs_fsize != fsize)
384 printf("\t%s to be changed from %d to %d\n",
385 "and the fragment size",
386 fsize, sblock.fs_fsize);
387 exit(23);
388 }
389 /*
390 * Calculate the number of cylinders per group
391 */
392 sblock.fs_cpg = cpg;
393 if (sblock.fs_cpg % mincpc != 0) {
394 printf("%s groups must have a multiple of %d cylinders\n",
395 cpgflg ? "Cylinder" : "Warning: cylinder", mincpc);
396 sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc);
397 if (!cpgflg)
398 cpg = sblock.fs_cpg;
399 }
400 /*
401 * Must ensure there is enough space for inodes.
402 */
403 sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb);
404 while (sblock.fs_ipg > MAXIPG(&sblock)) {
405 inodecramped = 1;
406 sblock.fs_cpg -= mincpc;
407 sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb);
408 }
409 /*
410 * Must ensure there is enough space to hold block map.
411 */
412 while (CGSIZE(&sblock) > sblock.fs_bsize) {
413 mapcramped = 1;
414 sblock.fs_cpg -= mincpc;
415 sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb);
416 }
417 sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
418 if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) {
419 printf("panic (fs_cpg * fs_spc) %% NSPF != 0");
420 exit(24);
421 }
422 if (sblock.fs_cpg < mincpg) {
423 printf("cylinder groups must have at least %d cylinders\n",
424 mincpg);
425 exit(25);
426 } else if (sblock.fs_cpg != cpg && cpgflg) {
427 if (!mapcramped && !inodecramped)
428 exit(26);
429 if (mapcramped && inodecramped)
430 printf("Block size and bytes per inode restrict");
431 else if (mapcramped)
432 printf("Block size restricts");
433 else
434 printf("Bytes per inode restrict");
435 printf(" cylinders per group to %d.\n", sblock.fs_cpg);
436 exit(27);
437 }
438 sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock));
439 /*
440 * Now have size for file system and nsect and ntrak.
441 * Determine number of cylinders and blocks in the file system.
442 */
443 sblock.fs_size = fssize = dbtofsb(&sblock, fssize);
444 sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc;
445 if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) {
446 sblock.fs_ncyl++;
447 warned = 1;
448 }
449 if (sblock.fs_ncyl < 1) {
450 printf("file systems must have at least one cylinder\n");
451 exit(28);
452 }
453 /*
454 * Determine feasability/values of rotational layout tables.
455 *
456 * The size of the rotational layout tables is limited by the
457 * size of the superblock, SBSIZE. The amount of space available
458 * for tables is calculated as (SBSIZE - sizeof (struct fs)).
459 * The size of these tables is inversely proportional to the block
460 * size of the file system. The size increases if sectors per track
461 * are not powers of two, because more cylinders must be described
462 * by the tables before the rotational pattern repeats (fs_cpc).
463 */
464 sblock.fs_interleave = interleave;
465 sblock.fs_trackskew = trackskew;
466 sblock.fs_npsect = nphyssectors;
467 sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT;
468 sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs));
469 if (sblock.fs_ntrak == 1) {
470 sblock.fs_cpc = 0;
471 goto next;
472 }
473 postblsize = sblock.fs_nrpos * sblock.fs_cpc * sizeof(int16_t);
474 rotblsize = sblock.fs_cpc * sblock.fs_spc / NSPB(&sblock);
475 totalsbsize = sizeof(struct fs) + rotblsize;
476 if (sblock.fs_nrpos == 8 && sblock.fs_cpc <= 16) {
477 /* use old static table space */
478 sblock.fs_postbloff = (char *)(&sblock.fs_opostbl[0][0]) -
479 (char *)(&sblock.fs_firstfield);
480 sblock.fs_rotbloff = &sblock.fs_space[0] -
481 (u_char *)(&sblock.fs_firstfield);
482 } else {
483 /* use dynamic table space */
484 sblock.fs_postbloff = &sblock.fs_space[0] -
485 (u_char *)(&sblock.fs_firstfield);
486 sblock.fs_rotbloff = sblock.fs_postbloff + postblsize;
487 totalsbsize += postblsize;
488 }
489 if (totalsbsize > SBSIZE ||
490 sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) {
491 printf("%s %s %d %s %d.%s",
492 "Warning: insufficient space in super block for\n",
493 "rotational layout tables with nsect", sblock.fs_nsect,
494 "and ntrak", sblock.fs_ntrak,
495 "\nFile system performance may be impaired.\n");
496 sblock.fs_cpc = 0;
497 goto next;
498 }
499 sblock.fs_sbsize = fragroundup(&sblock, totalsbsize);
500 /*
501 * calculate the available blocks for each rotational position
502 */
503 for (cylno = 0; cylno < sblock.fs_cpc; cylno++)
504 for (rpos = 0; rpos < sblock.fs_nrpos; rpos++)
505 fs_postbl(&sblock, cylno)[rpos] = -1;
506 for (i = (rotblsize - 1) * sblock.fs_frag;
507 i >= 0; i -= sblock.fs_frag) {
508 cylno = cbtocylno(&sblock, i);
509 rpos = cbtorpos(&sblock, i);
510 blk = fragstoblks(&sblock, i);
511 if (fs_postbl(&sblock, cylno)[rpos] == -1)
512 fs_rotbl(&sblock)[blk] = 0;
513 else
514 fs_rotbl(&sblock)[blk] = fs_postbl(&sblock, cylno)[rpos] - blk;
515 fs_postbl(&sblock, cylno)[rpos] = blk;
516 }
517 next:
518 /*
519 * Compute/validate number of cylinder groups.
520 */
521 sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg;
522 if (sblock.fs_ncyl % sblock.fs_cpg)
523 sblock.fs_ncg++;
524 sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock);
525 i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1);
526 if (cgdmin(&sblock, i) - cgbase(&sblock, i) >= sblock.fs_fpg) {
527 printf("inode blocks/cyl group (%d) >= data blocks (%d)\n",
528 cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag,
529 sblock.fs_fpg / sblock.fs_frag);
530 printf("number of cylinders per cylinder group (%d) %s.\n",
531 sblock.fs_cpg, "must be increased");
532 exit(29);
533 }
534 j = sblock.fs_ncg - 1;
535 if ((i = fssize - j * sblock.fs_fpg) < sblock.fs_fpg &&
536 cgdmin(&sblock, j) - cgbase(&sblock, j) > i) {
537 if (j == 0) {
538 printf("File system must have at least %d sectors\n",
539 NSPF(&sblock) *
540 (cgdmin(&sblock, 0) + 3 * sblock.fs_frag));
541 exit(30);
542 }
543 printf("Warning: inode blocks/cyl group (%d) >= "
544 "data blocks (%d) in last\n",
545 (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag,
546 i / sblock.fs_frag);
547 printf(" cylinder group. This implies %d sector(s) "
548 "cannot be allocated.\n",
549 i * NSPF(&sblock));
550 sblock.fs_ncg--;
551 sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg;
552 sblock.fs_size = fssize = sblock.fs_ncyl * sblock.fs_spc /
553 NSPF(&sblock);
554 warned = 0;
555 }
556 if (warned) {
557 printf("Warning: %d sector(s) in last cylinder unallocated\n",
558 sblock.fs_spc -
559 (fssize * NSPF(&sblock) - (sblock.fs_ncyl - 1)
560 * sblock.fs_spc));
561 }
562 /*
563 * fill in remaining fields of the super block
564 */
565 sblock.fs_csaddr = cgdmin(&sblock, 0);
566 sblock.fs_cssize =
567 fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum));
568 /*
569 * The superblock fields 'fs_csmask' and 'fs_csshift' are no
570 * longer used. However, we still initialise them so that the
571 * filesystem remains compatible with old kernels.
572 */
573 i = sblock.fs_bsize / sizeof(struct csum);
574 sblock.fs_csmask = ~(i - 1);
575 for (sblock.fs_csshift = 0; i > 1; i >>= 1)
576 sblock.fs_csshift++;
577
578 /*
579 * Setup memory for temporary in-core cylgroup summaries.
580 * Cribbed from ffs_mountfs().
581 */
582 size = sblock.fs_cssize;
583 blks = howmany(size, sblock.fs_fsize);
584 if (sblock.fs_contigsumsize > 0)
585 size += sblock.fs_ncg * sizeof(int32_t);
586 if ((space = (char *)calloc(1, size)) == NULL)
587 err(1, "memory allocation error for cg summaries");
588 sblock.fs_csp = space;
589 space = (char *)space + sblock.fs_cssize;
590 if (sblock.fs_contigsumsize > 0) {
591 int32_t *lp;
592
593 sblock.fs_maxcluster = lp = space;
594 for (i = 0; i < sblock.fs_ncg; i++)
595 *lp++ = sblock.fs_contigsumsize;
596 }
597
598 sblock.fs_magic = FS_MAGIC;
599 sblock.fs_rotdelay = rotdelay;
600 sblock.fs_minfree = minfree;
601 sblock.fs_maxcontig = maxcontig;
602 sblock.fs_maxbpg = maxbpg;
603 sblock.fs_rps = rpm / 60;
604 sblock.fs_optim = opt;
605 sblock.fs_cgrotor = 0;
606 sblock.fs_cstotal.cs_ndir = 0;
607 sblock.fs_cstotal.cs_nbfree = 0;
608 sblock.fs_cstotal.cs_nifree = 0;
609 sblock.fs_cstotal.cs_nffree = 0;
610 sblock.fs_fmod = 0;
611 sblock.fs_clean = FS_ISCLEAN;
612 sblock.fs_ronly = 0;
613
614 /*
615 * Dump out summary information about file system.
616 */
617 printf("%s:\t%d sectors in %d %s of %d tracks, %d sectors\n",
618 fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl,
619 "cylinders", sblock.fs_ntrak, sblock.fs_nsect);
620 #define B2MBFACTOR (1 / (1024.0 * 1024.0))
621 printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)\n",
622 (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR,
623 sblock.fs_ncg, sblock.fs_cpg,
624 (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR,
625 sblock.fs_ipg);
626 #undef B2MBFACTOR
627 /*
628 * Now determine how wide each column will be, and calculate how
629 * many columns will fit in a 76 char line. 76 is the width of the
630 * subwindows in sysinst.
631 */
632 printcolwidth = count_digits(
633 fsbtodb(&sblock, cgsblock(&sblock, sblock.fs_ncg -1)));
634 nprintcols = 76 / (printcolwidth + 2);
635 /*
636 * Now build the cylinders group blocks and
637 * then print out indices of cylinder groups.
638 */
639 printf("super-block backups (for fsck -b #) at:");
640 for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
641 initcg(cylno, start_time.tv_sec, fsopts);
642 if (cylno % nprintcols == 0)
643 printf("\n");
644 printf(" %*d,", printcolwidth,
645 fsbtodb(&sblock, cgsblock(&sblock, cylno)));
646 fflush(stdout);
647 }
648 printf("\n");
649
650 /*
651 * Now construct the initial file system,
652 * then write out the super-block.
653 */
654 sblock.fs_time = start_time.tv_sec;
655 if (fsopts->needswap)
656 sblock.fs_flags |= FS_SWAPPED;
657 ffs_write_superblock(&sblock, fsopts);
658 return (&sblock);
659 }
660
661 /*
662 * Write out the superblock and its duplicates,
663 * and the cylinder group summaries
664 */
665 void
666 ffs_write_superblock(struct fs *fs, const fsinfo_t *fsopts)
667 {
668 int cylno, size, blks, i, saveflag;
669 void *space;
670 char *wrbuf;
671
672 saveflag = fs->fs_flags & FS_INTERNAL;
673 fs->fs_flags &= ~FS_INTERNAL;
674
675 /* Write out the master super block */
676 memcpy(writebuf, fs, sbsize);
677 if (fsopts->needswap)
678 ffs_sb_swap(fs, (struct fs*)writebuf);
679 ffs_wtfs((int)SBOFF / sectorsize, sbsize, writebuf, fsopts);
680
681 /* Write out the duplicate super blocks */
682 for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
683 ffs_wtfs(fsbtodb(fs, cgsblock(fs, cylno)),
684 sbsize, writebuf, fsopts);
685
686 /* Write out the cylinder group summaries */
687 size = fs->fs_cssize;
688 blks = howmany(size, fs->fs_fsize);
689 space = (void *)fs->fs_csp;
690 if ((wrbuf = malloc(size)) == NULL)
691 err(1, "ffs_write_superblock: malloc %d", size);
692 for (i = 0; i < blks; i+= fs->fs_frag) {
693 size = fs->fs_bsize;
694 if (i + fs->fs_frag > blks)
695 size = (blks - i) * fs->fs_fsize;
696 if (fsopts->needswap)
697 ffs_csum_swap((struct csum *)space,
698 (struct csum *)wrbuf, size);
699 else
700 memcpy(wrbuf, space, (u_int)size);
701 ffs_wtfs(fsbtodb(fs, fs->fs_csaddr + i), size, wrbuf, fsopts);
702 space = (char *)space + size;
703 }
704 free(wrbuf);
705 fs->fs_flags |= saveflag;
706 }
707
708
709 /*
710 * Initialize a cylinder group.
711 */
712 static void
713 initcg(int cylno, time_t utime, const fsinfo_t *fsopts)
714 {
715 daddr_t cbase, d, dlower, dupper, dmax, blkno;
716 int32_t i;
717
718 /*
719 * Determine block bounds for cylinder group.
720 * Allow space for super block summary information in first
721 * cylinder group.
722 */
723 cbase = cgbase(&sblock, cylno);
724 dmax = cbase + sblock.fs_fpg;
725 if (dmax > sblock.fs_size)
726 dmax = sblock.fs_size;
727 dlower = cgsblock(&sblock, cylno) - cbase;
728 dupper = cgdmin(&sblock, cylno) - cbase;
729 if (cylno == 0)
730 dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
731 memset(&acg, 0, sblock.fs_cgsize);
732 acg.cg_time = utime;
733 acg.cg_magic = CG_MAGIC;
734 acg.cg_cgx = cylno;
735 if (cylno == sblock.fs_ncg - 1)
736 acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
737 else
738 acg.cg_ncyl = sblock.fs_cpg;
739 acg.cg_niblk = sblock.fs_ipg;
740 acg.cg_ndblk = dmax - cbase;
741 if (sblock.fs_contigsumsize > 0)
742 acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag;
743 acg.cg_btotoff = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
744 acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(int32_t);
745 acg.cg_iusedoff = acg.cg_boff +
746 sblock.fs_cpg * sblock.fs_nrpos * sizeof(int16_t);
747 acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY);
748 if (sblock.fs_contigsumsize <= 0) {
749 acg.cg_nextfreeoff = acg.cg_freeoff +
750 howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY);
751 } else {
752 acg.cg_clustersumoff = acg.cg_freeoff + howmany
753 (sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY) -
754 sizeof(int32_t);
755 acg.cg_clustersumoff =
756 roundup(acg.cg_clustersumoff, sizeof(int32_t));
757 acg.cg_clusteroff = acg.cg_clustersumoff +
758 (sblock.fs_contigsumsize + 1) * sizeof(int32_t);
759 acg.cg_nextfreeoff = acg.cg_clusteroff + howmany
760 (sblock.fs_cpg * sblock.fs_spc / NSPB(&sblock), NBBY);
761 }
762 if (acg.cg_nextfreeoff > sblock.fs_cgsize) {
763 printf("Panic: cylinder group too big\n");
764 exit(37);
765 }
766 acg.cg_cs.cs_nifree += sblock.fs_ipg;
767 if (cylno == 0)
768 for (i = 0; i < ROOTINO; i++) {
769 setbit(cg_inosused(&acg, 0), i);
770 acg.cg_cs.cs_nifree--;
771 }
772 for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag)
773 ffs_wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i),
774 sblock.fs_bsize, (char *)zino, fsopts);
775 if (cylno > 0) {
776 /*
777 * In cylno 0, beginning space is reserved
778 * for boot and super blocks.
779 */
780 for (d = 0; d < dlower; d += sblock.fs_frag) {
781 blkno = d / sblock.fs_frag;
782 ffs_setblock(&sblock, cg_blksfree(&acg, 0), blkno);
783 if (sblock.fs_contigsumsize > 0)
784 setbit(cg_clustersfree(&acg, 0), blkno);
785 acg.cg_cs.cs_nbfree++;
786 cg_blktot(&acg, 0)[cbtocylno(&sblock, d)]++;
787 cg_blks(&sblock, &acg, cbtocylno(&sblock, d), 0)
788 [cbtorpos(&sblock, d)]++;
789 }
790 sblock.fs_dsize += dlower;
791 }
792 sblock.fs_dsize += acg.cg_ndblk - dupper;
793 if ((i = (dupper % sblock.fs_frag)) != 0) {
794 acg.cg_frsum[sblock.fs_frag - i]++;
795 for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
796 setbit(cg_blksfree(&acg, 0), dupper);
797 acg.cg_cs.cs_nffree++;
798 }
799 }
800 for (d = dupper; d + sblock.fs_frag <= dmax - cbase; ) {
801 blkno = d / sblock.fs_frag;
802 ffs_setblock(&sblock, cg_blksfree(&acg, 0), blkno);
803 if (sblock.fs_contigsumsize > 0)
804 setbit(cg_clustersfree(&acg, 0), blkno);
805 acg.cg_cs.cs_nbfree++;
806 cg_blktot(&acg, 0)[cbtocylno(&sblock, d)]++;
807 cg_blks(&sblock, &acg, cbtocylno(&sblock, d), 0)
808 [cbtorpos(&sblock, d)]++;
809 d += sblock.fs_frag;
810 }
811 if (d < dmax - cbase) {
812 acg.cg_frsum[dmax - cbase - d]++;
813 for (; d < dmax - cbase; d++) {
814 setbit(cg_blksfree(&acg, 0), d);
815 acg.cg_cs.cs_nffree++;
816 }
817 }
818 if (sblock.fs_contigsumsize > 0) {
819 int32_t *sump = cg_clustersum(&acg, 0);
820 u_char *mapp = cg_clustersfree(&acg, 0);
821 int map = *mapp++;
822 int bit = 1;
823 int run = 0;
824
825 for (i = 0; i < acg.cg_nclusterblks; i++) {
826 if ((map & bit) != 0) {
827 run++;
828 } else if (run != 0) {
829 if (run > sblock.fs_contigsumsize)
830 run = sblock.fs_contigsumsize;
831 sump[run]++;
832 run = 0;
833 }
834 if ((i & (NBBY - 1)) != (NBBY - 1)) {
835 bit <<= 1;
836 } else {
837 map = *mapp++;
838 bit = 1;
839 }
840 }
841 if (run != 0) {
842 if (run > sblock.fs_contigsumsize)
843 run = sblock.fs_contigsumsize;
844 sump[run]++;
845 }
846 }
847 sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir;
848 sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree;
849 sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
850 sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree;
851 sblock.fs_cs(&sblock, cylno) = acg.cg_cs;
852 memcpy(writebuf, &acg, sblock.fs_bsize);
853 if (fsopts->needswap)
854 swap_cg(&acg, (struct cg*)writebuf);
855 ffs_wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)),
856 sblock.fs_bsize,
857 writebuf, fsopts);
858 }
859
860 /*
861 * Calculate number of inodes per group.
862 */
863 static int32_t
864 calcipg(int32_t cylpg, int32_t bpcg, off_t *usedbp)
865 {
866 int i;
867 int32_t ipg, new_ipg, ncg, ncyl;
868 off_t usedb;
869
870 /*
871 * Prepare to scale by fssize / (number of sectors in cylinder groups).
872 * Note that fssize is still in sectors, not file system blocks.
873 */
874 ncyl = howmany(fssize, secpercyl);
875 ncg = howmany(ncyl, cylpg);
876 /*
877 * Iterate a few times to allow for ipg depending on itself.
878 */
879 ipg = 0;
880 for (i = 0; i < 10; i++) {
881 usedb = (sblock.fs_iblkno + ipg / INOPF(&sblock))
882 * NSPF(&sblock) * (off_t)sectorsize;
883 if (cylpg * (long long)bpcg < usedb) {
884 warnx("Too many inodes per cyl group!");
885 return (MAXIPG(&sblock)+1);
886 }
887 new_ipg = (cylpg * (long long)bpcg - usedb) /
888 (long long)density * fssize / (ncg * secpercyl * cylpg);
889 if (new_ipg <= 0)
890 new_ipg = 1; /* ensure ipg > 0 */
891 new_ipg = roundup(new_ipg, INOPB(&sblock));
892 if (new_ipg == ipg)
893 break;
894 ipg = new_ipg;
895 }
896 *usedbp = usedb;
897 return (ipg);
898 }
899
900
901 /*
902 * read a block from the file system
903 */
904 void
905 ffs_rdfs(daddr_t bno, int size, void *bf, const fsinfo_t *fsopts)
906 {
907 int n;
908 off_t offset;
909
910 offset = bno;
911 offset *= fsopts->sectorsize;
912 if (lseek(fsopts->fd, offset, SEEK_SET) < 0)
913 err(1, "ffs_rdfs: seek error: %d\n", bno);
914 n = read(fsopts->fd, bf, size);
915 if (n == -1)
916 err(1, "ffs_rdfs: read error bno %d size %d\n", bno, size);
917 else if (n != size)
918 errx(1,
919 "ffs_rdfs: read error bno %d size %d: short read of %d\n",
920 bno, size, n);
921 }
922
923 /*
924 * write a block to the file system
925 */
926 void
927 ffs_wtfs(daddr_t bno, int size, void *bf, const fsinfo_t *fsopts)
928 {
929 int n;
930 off_t offset;
931
932 offset = bno;
933 offset *= fsopts->sectorsize;
934 if (lseek(fsopts->fd, offset, SEEK_SET) < 0)
935 err(1, "ffs_wtfs: seek error: %d\n", bno);
936 n = write(fsopts->fd, bf, size);
937 if (n == -1)
938 err(1, "ffs_wtfs: write error bno %d size %d\n", bno, size);
939 else if (n != size)
940 errx(1,
941 "ffs_wtfs: write error bno %d size %d: short write of %d\n",
942 bno, size, n);
943 }
944
945 /* swap byte order of cylinder group */
946 static void
947 swap_cg(struct cg *o, struct cg *n)
948 {
949 int i, btotsize, fbsize;
950 u_int32_t *n32, *o32;
951 u_int16_t *n16, *o16;
952
953 n->cg_firstfield = bswap32(o->cg_firstfield);
954 n->cg_magic = bswap32(o->cg_magic);
955 n->cg_time = bswap32(o->cg_time);
956 n->cg_cgx = bswap32(o->cg_cgx);
957 n->cg_ncyl = bswap16(o->cg_ncyl);
958 n->cg_niblk = bswap16(o->cg_niblk);
959 n->cg_ndblk = bswap32(o->cg_ndblk);
960 n->cg_cs.cs_ndir = bswap32(o->cg_cs.cs_ndir);
961 n->cg_cs.cs_nbfree = bswap32(o->cg_cs.cs_nbfree);
962 n->cg_cs.cs_nifree = bswap32(o->cg_cs.cs_nifree);
963 n->cg_cs.cs_nffree = bswap32(o->cg_cs.cs_nffree);
964 n->cg_rotor = bswap32(o->cg_rotor);
965 n->cg_frotor = bswap32(o->cg_frotor);
966 n->cg_irotor = bswap32(o->cg_irotor);
967 n->cg_btotoff = bswap32(o->cg_btotoff);
968 n->cg_boff = bswap32(o->cg_boff);
969 n->cg_iusedoff = bswap32(o->cg_iusedoff);
970 n->cg_freeoff = bswap32(o->cg_freeoff);
971 n->cg_nextfreeoff = bswap32(o->cg_nextfreeoff);
972 n->cg_clustersumoff = bswap32(o->cg_clustersumoff);
973 n->cg_clusteroff = bswap32(o->cg_clusteroff);
974 n->cg_nclusterblks = bswap32(o->cg_nclusterblks);
975 for (i=0; i < MAXFRAG; i++)
976 n->cg_frsum[i] = bswap32(o->cg_frsum[i]);
977
978 /* alays new format */
979 if (n->cg_magic == CG_MAGIC) {
980 btotsize = n->cg_boff - n->cg_btotoff;
981 fbsize = n->cg_iusedoff - n->cg_boff;
982 n32 = (u_int32_t*)((u_int8_t*)n + n->cg_btotoff);
983 o32 = (u_int32_t*)((u_int8_t*)o + n->cg_btotoff);
984 n16 = (u_int16_t*)((u_int8_t*)n + n->cg_boff);
985 o16 = (u_int16_t*)((u_int8_t*)o + n->cg_boff);
986 } else {
987 btotsize = bswap32(n->cg_boff) - bswap32(n->cg_btotoff);
988 fbsize = bswap32(n->cg_iusedoff) - bswap32(n->cg_boff);
989 n32 = (u_int32_t*)((u_int8_t*)n + bswap32(n->cg_btotoff));
990 o32 = (u_int32_t*)((u_int8_t*)o + bswap32(n->cg_btotoff));
991 n16 = (u_int16_t*)((u_int8_t*)n + bswap32(n->cg_boff));
992 o16 = (u_int16_t*)((u_int8_t*)o + bswap32(n->cg_boff));
993 }
994 for (i=0; i < btotsize / sizeof(u_int32_t); i++)
995 n32[i] = bswap32(o32[i]);
996
997 for (i=0; i < fbsize/sizeof(u_int16_t); i++)
998 n16[i] = bswap16(o16[i]);
999
1000 if (n->cg_magic == CG_MAGIC) {
1001 n32 = (u_int32_t*)((u_int8_t*)n + n->cg_clustersumoff);
1002 o32 = (u_int32_t*)((u_int8_t*)o + n->cg_clustersumoff);
1003 } else {
1004 n32 = (u_int32_t*)((u_int8_t*)n + bswap32(n->cg_clustersumoff));
1005 o32 = (u_int32_t*)((u_int8_t*)o + bswap32(n->cg_clustersumoff));
1006 }
1007 for (i = 1; i < sblock.fs_contigsumsize + 1; i++)
1008 n32[i] = bswap32(o32[i]);
1009 }
1010
1011 /* Determine how many digits are needed to print a given integer */
1012 static int
1013 count_digits(int num)
1014 {
1015 int ndig;
1016
1017 for(ndig = 1; num > 9; num /=10, ndig++);
1018
1019 return (ndig);
1020 }
1021