mkfs.c revision 1.12 1 /* $NetBSD: mkfs.c,v 1.12 2003/01/24 21:55:33 fvdl 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 #if defined(__RCSID) && !defined(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.12 2003/01/24 21:55:33 fvdl 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 <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <unistd.h>
54
55 #include "makefs.h"
56
57 #include <ufs/ufs/dinode.h>
58 #include <ufs/ufs/ufs_bswap.h>
59 #include <ufs/ffs/fs.h>
60
61 #include "ffs/ufs_inode.h"
62 #include "ffs/ffs_extern.h"
63 #include "ffs/newfs_extern.h"
64
65 static void initcg(int, time_t, const fsinfo_t *);
66 static int32_t calcipg(int32_t, int32_t, off_t *);
67 static void swap_cg(struct cg *, struct cg *);
68
69 static int count_digits(int);
70
71 /*
72 * make file system for cylinder-group style file systems
73 */
74
75 /*
76 * We limit the size of the inode map to be no more than a
77 * third of the cylinder group space, since we must leave at
78 * least an equal amount of space for the block map.
79 *
80 * N.B.: MAXIPG must be a multiple of INOPB(fs).
81 */
82 #define MAXIPG(fs) roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs))
83
84 #define UMASK 0755
85 #define POWEROF2(num) (((num) & ((num) - 1)) == 0)
86
87 union {
88 struct fs fs;
89 char pad[SBSIZE];
90 } fsun;
91 #define sblock fsun.fs
92
93 union {
94 struct cg cg;
95 char pad[MAXBSIZE];
96 } cgun;
97 #define acg cgun.cg
98
99 struct dinode zino[MAXBSIZE / DINODE_SIZE];
100
101 char writebuf[MAXBSIZE];
102
103 static int Oflag; /* format as an 4.3BSD file system */
104 static int fssize; /* file system size */
105 static int ntracks; /* # tracks/cylinder */
106 static int nsectors; /* # sectors/track */
107 static int nphyssectors; /* # sectors/track including spares */
108 static int secpercyl; /* sectors per cylinder */
109 static int sectorsize; /* bytes/sector */
110 static int rpm; /* revolutions/minute of drive */
111 static int interleave; /* hardware sector interleave */
112 static int trackskew; /* sector 0 skew, per track */
113 static int fsize; /* fragment size */
114 static int bsize; /* block size */
115 static int cpg; /* cylinders/cylinder group */
116 static int cpgflg; /* cylinders/cylinder group flag was given */
117 static int minfree; /* free space threshold */
118 static int opt; /* optimization preference (space or time) */
119 static int density; /* number of bytes per inode */
120 static int maxcontig; /* max contiguous blocks to allocate */
121 static int rotdelay; /* rotational delay between blocks */
122 static int maxbpg; /* maximum blocks per file in a cyl group */
123 static int nrpos; /* # of distinguished rotational positions */
124 static int bbsize; /* boot block size */
125 static int sbsize; /* superblock size */
126 static int avgfilesize; /* expected average file size */
127 static int avgfpdir; /* expected number of files per directory */
128
129
130 struct fs *
131 ffs_mkfs(const char *fsys, const fsinfo_t *fsopts)
132 {
133 int32_t i, mincpc, mincpg, inospercg;
134 int32_t cylno, rpos, blk, j, warned = 0;
135 int32_t used, mincpgcnt, bpcg;
136 off_t usedb;
137 int32_t mapcramped, inodecramped;
138 int32_t postblsize, rotblsize, totalsbsize;
139 long long sizepb;
140 void *space;
141 int size, blks;
142 int nprintcols, printcolwidth;
143
144 Oflag = 0;
145 fssize = fsopts->size / fsopts->sectorsize;
146 ntracks = fsopts->ntracks;
147 nsectors = fsopts->nsectors;
148 nphyssectors = fsopts->nsectors; /* XXX: no trackspares */
149 secpercyl = nsectors * ntracks;
150 sectorsize = fsopts->sectorsize;
151 rpm = fsopts->rpm;
152 interleave = 1;
153 trackskew = 0;
154 fsize = fsopts->fsize;
155 bsize = fsopts->bsize;
156 cpg = fsopts->cpg;
157 cpgflg = fsopts->cpgflg;
158 minfree = fsopts->minfree;
159 opt = fsopts->optimization;
160 density = fsopts->density;
161 maxcontig = fsopts->maxcontig;
162 rotdelay = fsopts->rotdelay;
163 maxbpg = fsopts->maxbpg;
164 nrpos = fsopts->nrpos;
165 bbsize = BBSIZE;
166 sbsize = SBSIZE;
167 avgfilesize = fsopts->avgfilesize;
168 avgfpdir = fsopts->avgfpdir;
169
170 if (Oflag) {
171 sblock.fs_inodefmt = FS_42INODEFMT;
172 sblock.fs_maxsymlinklen = 0;
173 } else {
174 sblock.fs_inodefmt = FS_44INODEFMT;
175 sblock.fs_maxsymlinklen = MAXSYMLINKLEN;
176 }
177 /*
178 * Validate the given file system size.
179 * Verify that its last block can actually be accessed.
180 */
181 if (fssize <= 0)
182 printf("preposterous size %d\n", fssize), exit(13);
183 ffs_wtfs(fssize - 1, sectorsize, (char *)&sblock, fsopts);
184
185 /*
186 * collect and verify the sector and track info
187 */
188 sblock.fs_nsect = nsectors;
189 sblock.fs_ntrak = ntracks;
190 if (sblock.fs_ntrak <= 0)
191 printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(14);
192 if (sblock.fs_nsect <= 0)
193 printf("preposterous nsect %d\n", sblock.fs_nsect), exit(15);
194 /*
195 * collect and verify the filesystem density info
196 */
197 sblock.fs_avgfilesize = avgfilesize;
198 sblock.fs_avgfpdir = avgfpdir;
199 if (sblock.fs_avgfilesize <= 0)
200 printf("illegal expected average file size %d\n",
201 sblock.fs_avgfilesize), exit(14);
202 if (sblock.fs_avgfpdir <= 0)
203 printf("illegal expected number of files per directory %d\n",
204 sblock.fs_avgfpdir), exit(15);
205 /*
206 * collect and verify the block and fragment sizes
207 */
208 sblock.fs_bsize = bsize;
209 sblock.fs_fsize = fsize;
210 if (!POWEROF2(sblock.fs_bsize)) {
211 printf("block size must be a power of 2, not %d\n",
212 sblock.fs_bsize);
213 exit(16);
214 }
215 if (!POWEROF2(sblock.fs_fsize)) {
216 printf("fragment size must be a power of 2, not %d\n",
217 sblock.fs_fsize);
218 exit(17);
219 }
220 if (sblock.fs_fsize < sectorsize) {
221 printf("fragment size %d is too small, minimum is %d\n",
222 sblock.fs_fsize, sectorsize);
223 exit(18);
224 }
225 if (sblock.fs_bsize > MAXBSIZE) {
226 printf("block size %d is too large, maximum is %d\n",
227 sblock.fs_bsize, MAXBSIZE);
228 exit(19);
229 }
230 if (sblock.fs_bsize < MINBSIZE) {
231 printf("block size %d is too small, minimum is %d\n",
232 sblock.fs_bsize, MINBSIZE);
233 exit(19);
234 }
235 if (sblock.fs_bsize < sblock.fs_fsize) {
236 printf("block size (%d) cannot be smaller than fragment size (%d)\n",
237 sblock.fs_bsize, sblock.fs_fsize);
238 exit(20);
239 }
240 sblock.fs_bmask = ~(sblock.fs_bsize - 1);
241 sblock.fs_fmask = ~(sblock.fs_fsize - 1);
242 sblock.fs_qbmask = ~sblock.fs_bmask;
243 sblock.fs_qfmask = ~sblock.fs_fmask;
244 for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1)
245 sblock.fs_bshift++;
246 for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1)
247 sblock.fs_fshift++;
248 sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize);
249 for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1)
250 sblock.fs_fragshift++;
251 if (sblock.fs_frag > MAXFRAG) {
252 printf("fragment size %d is too small, "
253 "minimum with block size %d is %d\n",
254 sblock.fs_fsize, sblock.fs_bsize,
255 sblock.fs_bsize / MAXFRAG);
256 exit(21);
257 }
258 sblock.fs_nrpos = nrpos;
259 /* XXX ondisk32 */
260 sblock.fs_nindir = sblock.fs_bsize / sizeof(int32_t);
261 sblock.fs_inopb = sblock.fs_bsize / DINODE_SIZE;
262 sblock.fs_nspf = sblock.fs_fsize / sectorsize;
263 for (sblock.fs_fsbtodb = 0, i = NSPF(&sblock); i > 1; i >>= 1)
264 sblock.fs_fsbtodb++;
265 sblock.fs_sblkno =
266 roundup(howmany(bbsize + sbsize, sblock.fs_fsize), sblock.fs_frag);
267 /* XXX ondisk32 */
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 (%lld) >= data blocks (%d)\n",
528 (long long)cgdmin(&sblock, i) -
529 cgbase(&sblock, i) / sblock.fs_frag,
530 sblock.fs_fpg / sblock.fs_frag);
531 printf("number of cylinders per cylinder group (%d) %s.\n",
532 sblock.fs_cpg, "must be increased");
533 exit(29);
534 }
535 j = sblock.fs_ncg - 1;
536 if ((i = fssize - j * sblock.fs_fpg) < sblock.fs_fpg &&
537 cgdmin(&sblock, j) - cgbase(&sblock, j) > i) {
538 if (j == 0) {
539 printf("File system must have at least %lld sectors\n",
540 (long long)NSPF(&sblock) *
541 (cgdmin(&sblock, 0) + 3 * sblock.fs_frag));
542 exit(30);
543 }
544 printf("Warning: inode blocks/cyl group (%lld) >= "
545 "data blocks (%d) in last\n",
546 (long long)(cgdmin(&sblock, j) - cgbase(&sblock, j))
547 / sblock.fs_frag,
548 i / sblock.fs_frag);
549 printf(" cylinder group. This implies %d sector(s) "
550 "cannot be allocated.\n",
551 i * NSPF(&sblock));
552 sblock.fs_ncg--;
553 sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg;
554 sblock.fs_size = fssize = sblock.fs_ncyl * sblock.fs_spc /
555 NSPF(&sblock);
556 warned = 0;
557 }
558 if (warned) {
559 printf("Warning: %d sector(s) in last cylinder unallocated\n",
560 sblock.fs_spc -
561 (fssize * NSPF(&sblock) - (sblock.fs_ncyl - 1)
562 * sblock.fs_spc));
563 }
564 /*
565 * fill in remaining fields of the super block
566 */
567 sblock.fs_csaddr = cgdmin(&sblock, 0);
568 sblock.fs_cssize =
569 fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum));
570 /*
571 * The superblock fields 'fs_csmask' and 'fs_csshift' are no
572 * longer used. However, we still initialise them so that the
573 * filesystem remains compatible with old kernels.
574 */
575 i = sblock.fs_bsize / sizeof(struct csum);
576 sblock.fs_csmask = ~(i - 1);
577 for (sblock.fs_csshift = 0; i > 1; i >>= 1)
578 sblock.fs_csshift++;
579
580 /*
581 * Setup memory for temporary in-core cylgroup summaries.
582 * Cribbed from ffs_mountfs().
583 */
584 size = sblock.fs_cssize;
585 blks = howmany(size, sblock.fs_fsize);
586 if (sblock.fs_contigsumsize > 0)
587 size += sblock.fs_ncg * sizeof(int32_t);
588 if ((space = (char *)calloc(1, size)) == NULL)
589 err(1, "memory allocation error for cg summaries");
590 sblock.fs_csp = space;
591 space = (char *)space + sblock.fs_cssize;
592 if (sblock.fs_contigsumsize > 0) {
593 int32_t *lp;
594
595 sblock.fs_maxcluster = lp = space;
596 for (i = 0; i < sblock.fs_ncg; i++)
597 *lp++ = sblock.fs_contigsumsize;
598 }
599
600 sblock.fs_magic = FS_MAGIC;
601 sblock.fs_rotdelay = rotdelay;
602 sblock.fs_minfree = minfree;
603 sblock.fs_maxcontig = maxcontig;
604 sblock.fs_maxbpg = maxbpg;
605 sblock.fs_rps = rpm / 60;
606 sblock.fs_optim = opt;
607 sblock.fs_cgrotor = 0;
608 sblock.fs_cstotal.cs_ndir = 0;
609 sblock.fs_cstotal.cs_nbfree = 0;
610 sblock.fs_cstotal.cs_nifree = 0;
611 sblock.fs_cstotal.cs_nffree = 0;
612 sblock.fs_fmod = 0;
613 sblock.fs_clean = FS_ISCLEAN;
614 sblock.fs_ronly = 0;
615
616 /*
617 * Dump out summary information about file system.
618 */
619 printf("%s:\t%d sectors in %d %s of %d tracks, %d sectors\n",
620 fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl,
621 "cylinders", sblock.fs_ntrak, sblock.fs_nsect);
622 #define B2MBFACTOR (1 / (1024.0 * 1024.0))
623 printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)\n",
624 (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR,
625 sblock.fs_ncg, sblock.fs_cpg,
626 (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR,
627 sblock.fs_ipg);
628 #undef B2MBFACTOR
629 /*
630 * Now determine how wide each column will be, and calculate how
631 * many columns will fit in a 76 char line. 76 is the width of the
632 * subwindows in sysinst.
633 */
634 printcolwidth = count_digits(
635 fsbtodb(&sblock, cgsblock(&sblock, sblock.fs_ncg -1)));
636 nprintcols = 76 / (printcolwidth + 2);
637 /*
638 * Now build the cylinders group blocks and
639 * then print out indices of cylinder groups.
640 */
641 printf("super-block backups (for fsck -b #) at:");
642 for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
643 initcg(cylno, start_time.tv_sec, fsopts);
644 if (cylno % nprintcols == 0)
645 printf("\n");
646 printf(" %*lld,", printcolwidth,
647 (long long)fsbtodb(&sblock, cgsblock(&sblock, cylno)));
648 fflush(stdout);
649 }
650 printf("\n");
651
652 /*
653 * Now construct the initial file system,
654 * then write out the super-block.
655 */
656 sblock.fs_time = start_time.tv_sec;
657 if (fsopts->needswap)
658 sblock.fs_flags |= FS_SWAPPED;
659 ffs_write_superblock(&sblock, fsopts);
660 return (&sblock);
661 }
662
663 /*
664 * Write out the superblock and its duplicates,
665 * and the cylinder group summaries
666 */
667 void
668 ffs_write_superblock(struct fs *fs, const fsinfo_t *fsopts)
669 {
670 int cylno, size, blks, i, saveflag;
671 void *space;
672 char *wrbuf;
673
674 saveflag = fs->fs_flags & FS_INTERNAL;
675 fs->fs_flags &= ~FS_INTERNAL;
676
677 /* Write out the master super block */
678 memcpy(writebuf, fs, sbsize);
679 if (fsopts->needswap)
680 ffs_sb_swap(fs, (struct fs*)writebuf);
681 ffs_wtfs((int)SBOFF / sectorsize, sbsize, writebuf, fsopts);
682
683 /* Write out the duplicate super blocks */
684 for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
685 ffs_wtfs(fsbtodb(fs, cgsblock(fs, cylno)),
686 sbsize, writebuf, fsopts);
687
688 /* Write out the cylinder group summaries */
689 size = fs->fs_cssize;
690 blks = howmany(size, fs->fs_fsize);
691 space = (void *)fs->fs_csp;
692 if ((wrbuf = malloc(size)) == NULL)
693 err(1, "ffs_write_superblock: malloc %d", size);
694 for (i = 0; i < blks; i+= fs->fs_frag) {
695 size = fs->fs_bsize;
696 if (i + fs->fs_frag > blks)
697 size = (blks - i) * fs->fs_fsize;
698 if (fsopts->needswap)
699 ffs_csum_swap((struct csum *)space,
700 (struct csum *)wrbuf, size);
701 else
702 memcpy(wrbuf, space, (u_int)size);
703 ffs_wtfs(fsbtodb(fs, fs->fs_csaddr + i), size, wrbuf, fsopts);
704 space = (char *)space + size;
705 }
706 free(wrbuf);
707 fs->fs_flags |= saveflag;
708 }
709
710
711 /*
712 * Initialize a cylinder group.
713 */
714 static void
715 initcg(int cylno, time_t utime, const fsinfo_t *fsopts)
716 {
717 daddr_t cbase, d, dlower, dupper, dmax, blkno;
718 int32_t i;
719
720 /*
721 * Determine block bounds for cylinder group.
722 * Allow space for super block summary information in first
723 * cylinder group.
724 */
725 cbase = cgbase(&sblock, cylno);
726 dmax = cbase + sblock.fs_fpg;
727 if (dmax > sblock.fs_size)
728 dmax = sblock.fs_size;
729 dlower = cgsblock(&sblock, cylno) - cbase;
730 dupper = cgdmin(&sblock, cylno) - cbase;
731 if (cylno == 0)
732 dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
733 memset(&acg, 0, sblock.fs_cgsize);
734 acg.cg_time = utime;
735 acg.cg_magic = CG_MAGIC;
736 acg.cg_cgx = cylno;
737 if (cylno == sblock.fs_ncg - 1)
738 acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
739 else
740 acg.cg_ncyl = sblock.fs_cpg;
741 acg.cg_niblk = sblock.fs_ipg;
742 acg.cg_ndblk = dmax - cbase;
743 if (sblock.fs_contigsumsize > 0)
744 acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag;
745 acg.cg_btotoff = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
746 acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(int32_t);
747 acg.cg_iusedoff = acg.cg_boff +
748 sblock.fs_cpg * sblock.fs_nrpos * sizeof(int16_t);
749 acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY);
750 if (sblock.fs_contigsumsize <= 0) {
751 acg.cg_nextfreeoff = acg.cg_freeoff +
752 howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY);
753 } else {
754 acg.cg_clustersumoff = acg.cg_freeoff + howmany
755 (sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY) -
756 sizeof(int32_t);
757 acg.cg_clustersumoff =
758 roundup(acg.cg_clustersumoff, sizeof(int32_t));
759 acg.cg_clusteroff = acg.cg_clustersumoff +
760 (sblock.fs_contigsumsize + 1) * sizeof(int32_t);
761 acg.cg_nextfreeoff = acg.cg_clusteroff + howmany
762 (sblock.fs_cpg * sblock.fs_spc / NSPB(&sblock), NBBY);
763 }
764 if (acg.cg_nextfreeoff > sblock.fs_cgsize) {
765 printf("Panic: cylinder group too big\n");
766 exit(37);
767 }
768 acg.cg_cs.cs_nifree += sblock.fs_ipg;
769 if (cylno == 0)
770 for (i = 0; i < ROOTINO; i++) {
771 setbit(cg_inosused(&acg, 0), i);
772 acg.cg_cs.cs_nifree--;
773 }
774 for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag)
775 ffs_wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i),
776 sblock.fs_bsize, (char *)zino, fsopts);
777 if (cylno > 0) {
778 /*
779 * In cylno 0, beginning space is reserved
780 * for boot and super blocks.
781 */
782 for (d = 0; d < dlower; d += sblock.fs_frag) {
783 blkno = d / sblock.fs_frag;
784 ffs_setblock(&sblock, cg_blksfree(&acg, 0), blkno);
785 if (sblock.fs_contigsumsize > 0)
786 setbit(cg_clustersfree(&acg, 0), blkno);
787 acg.cg_cs.cs_nbfree++;
788 cg_blktot(&acg, 0)[cbtocylno(&sblock, d)]++;
789 cg_blks(&sblock, &acg, cbtocylno(&sblock, d), 0)
790 [cbtorpos(&sblock, d)]++;
791 }
792 sblock.fs_dsize += dlower;
793 }
794 sblock.fs_dsize += acg.cg_ndblk - dupper;
795 if ((i = (dupper % sblock.fs_frag)) != 0) {
796 acg.cg_frsum[sblock.fs_frag - i]++;
797 for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
798 setbit(cg_blksfree(&acg, 0), dupper);
799 acg.cg_cs.cs_nffree++;
800 }
801 }
802 for (d = dupper; d + sblock.fs_frag <= dmax - cbase; ) {
803 blkno = d / sblock.fs_frag;
804 ffs_setblock(&sblock, cg_blksfree(&acg, 0), blkno);
805 if (sblock.fs_contigsumsize > 0)
806 setbit(cg_clustersfree(&acg, 0), blkno);
807 acg.cg_cs.cs_nbfree++;
808 cg_blktot(&acg, 0)[cbtocylno(&sblock, d)]++;
809 cg_blks(&sblock, &acg, cbtocylno(&sblock, d), 0)
810 [cbtorpos(&sblock, d)]++;
811 d += sblock.fs_frag;
812 }
813 if (d < dmax - cbase) {
814 acg.cg_frsum[dmax - cbase - d]++;
815 for (; d < dmax - cbase; d++) {
816 setbit(cg_blksfree(&acg, 0), d);
817 acg.cg_cs.cs_nffree++;
818 }
819 }
820 if (sblock.fs_contigsumsize > 0) {
821 int32_t *sump = cg_clustersum(&acg, 0);
822 u_char *mapp = cg_clustersfree(&acg, 0);
823 int map = *mapp++;
824 int bit = 1;
825 int run = 0;
826
827 for (i = 0; i < acg.cg_nclusterblks; i++) {
828 if ((map & bit) != 0) {
829 run++;
830 } else if (run != 0) {
831 if (run > sblock.fs_contigsumsize)
832 run = sblock.fs_contigsumsize;
833 sump[run]++;
834 run = 0;
835 }
836 if ((i & (NBBY - 1)) != (NBBY - 1)) {
837 bit <<= 1;
838 } else {
839 map = *mapp++;
840 bit = 1;
841 }
842 }
843 if (run != 0) {
844 if (run > sblock.fs_contigsumsize)
845 run = sblock.fs_contigsumsize;
846 sump[run]++;
847 }
848 }
849 sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir;
850 sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree;
851 sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
852 sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree;
853 sblock.fs_cs(&sblock, cylno) = acg.cg_cs;
854 memcpy(writebuf, &acg, sblock.fs_bsize);
855 if (fsopts->needswap)
856 swap_cg(&acg, (struct cg*)writebuf);
857 ffs_wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)),
858 sblock.fs_bsize,
859 writebuf, fsopts);
860 }
861
862 /*
863 * Calculate number of inodes per group.
864 */
865 static int32_t
866 calcipg(int32_t cylpg, int32_t bpcg, off_t *usedbp)
867 {
868 int i;
869 int32_t ipg, new_ipg, ncg, ncyl;
870 off_t usedb;
871
872 /*
873 * Prepare to scale by fssize / (number of sectors in cylinder groups).
874 * Note that fssize is still in sectors, not file system blocks.
875 */
876 ncyl = howmany(fssize, secpercyl);
877 ncg = howmany(ncyl, cylpg);
878 /*
879 * Iterate a few times to allow for ipg depending on itself.
880 */
881 ipg = 0;
882 for (i = 0; i < 10; i++) {
883 usedb = (sblock.fs_iblkno + ipg / INOPF(&sblock))
884 * NSPF(&sblock) * (off_t)sectorsize;
885 if (cylpg * (long long)bpcg < usedb) {
886 warnx("Too many inodes per cyl group!");
887 return (MAXIPG(&sblock)+1);
888 }
889 new_ipg = (cylpg * (long long)bpcg - usedb) /
890 (long long)density * fssize / (ncg * secpercyl * cylpg);
891 if (new_ipg <= 0)
892 new_ipg = 1; /* ensure ipg > 0 */
893 new_ipg = roundup(new_ipg, INOPB(&sblock));
894 if (new_ipg == ipg)
895 break;
896 ipg = new_ipg;
897 }
898 *usedbp = usedb;
899 return (ipg);
900 }
901
902
903 /*
904 * read a block from the file system
905 */
906 void
907 ffs_rdfs(daddr_t bno, int size, void *bf, const fsinfo_t *fsopts)
908 {
909 int n;
910 off_t offset;
911
912 offset = bno;
913 offset *= fsopts->sectorsize;
914 if (lseek(fsopts->fd, offset, SEEK_SET) < 0)
915 err(1, "ffs_rdfs: seek error: %lld", (long long)bno);
916 n = read(fsopts->fd, bf, size);
917 if (n == -1)
918 err(1, "ffs_rdfs: read error bno %lld size %d", (long long)bno,
919 size);
920 else if (n != size)
921 errx(1,
922 "ffs_rdfs: read error bno %lld size %d: short read of %d",
923 (long long)bno, size, n);
924 }
925
926 /*
927 * write a block to the file system
928 */
929 void
930 ffs_wtfs(daddr_t bno, int size, void *bf, const fsinfo_t *fsopts)
931 {
932 int n;
933 off_t offset;
934
935 offset = bno;
936 offset *= fsopts->sectorsize;
937 if (lseek(fsopts->fd, offset, SEEK_SET) < 0)
938 err(1, "ffs_wtfs: seek error: %lld", (long long)bno);
939 n = write(fsopts->fd, bf, size);
940 if (n == -1)
941 err(1, "ffs_wtfs: write error bno %lld size %d", (long long)bno, size);
942 else if (n != size)
943 errx(1,
944 "ffs_wtfs: write error bno %lld size %d: short write of %d",
945 (long long)bno, size, n);
946 }
947
948 /* swap byte order of cylinder group */
949 static void
950 swap_cg(struct cg *o, struct cg *n)
951 {
952 int i, btotsize, fbsize;
953 u_int32_t *n32, *o32;
954 u_int16_t *n16, *o16;
955
956 n->cg_firstfield = bswap32(o->cg_firstfield);
957 n->cg_magic = bswap32(o->cg_magic);
958 n->cg_time = bswap32(o->cg_time);
959 n->cg_cgx = bswap32(o->cg_cgx);
960 n->cg_ncyl = bswap16(o->cg_ncyl);
961 n->cg_niblk = bswap16(o->cg_niblk);
962 n->cg_ndblk = bswap32(o->cg_ndblk);
963 n->cg_cs.cs_ndir = bswap32(o->cg_cs.cs_ndir);
964 n->cg_cs.cs_nbfree = bswap32(o->cg_cs.cs_nbfree);
965 n->cg_cs.cs_nifree = bswap32(o->cg_cs.cs_nifree);
966 n->cg_cs.cs_nffree = bswap32(o->cg_cs.cs_nffree);
967 n->cg_rotor = bswap32(o->cg_rotor);
968 n->cg_frotor = bswap32(o->cg_frotor);
969 n->cg_irotor = bswap32(o->cg_irotor);
970 n->cg_btotoff = bswap32(o->cg_btotoff);
971 n->cg_boff = bswap32(o->cg_boff);
972 n->cg_iusedoff = bswap32(o->cg_iusedoff);
973 n->cg_freeoff = bswap32(o->cg_freeoff);
974 n->cg_nextfreeoff = bswap32(o->cg_nextfreeoff);
975 n->cg_clustersumoff = bswap32(o->cg_clustersumoff);
976 n->cg_clusteroff = bswap32(o->cg_clusteroff);
977 n->cg_nclusterblks = bswap32(o->cg_nclusterblks);
978 for (i=0; i < MAXFRAG; i++)
979 n->cg_frsum[i] = bswap32(o->cg_frsum[i]);
980
981 /* alays new format */
982 if (n->cg_magic == CG_MAGIC) {
983 btotsize = n->cg_boff - n->cg_btotoff;
984 fbsize = n->cg_iusedoff - n->cg_boff;
985 n32 = (u_int32_t*)((u_int8_t*)n + n->cg_btotoff);
986 o32 = (u_int32_t*)((u_int8_t*)o + n->cg_btotoff);
987 n16 = (u_int16_t*)((u_int8_t*)n + n->cg_boff);
988 o16 = (u_int16_t*)((u_int8_t*)o + n->cg_boff);
989 } else {
990 btotsize = bswap32(n->cg_boff) - bswap32(n->cg_btotoff);
991 fbsize = bswap32(n->cg_iusedoff) - bswap32(n->cg_boff);
992 n32 = (u_int32_t*)((u_int8_t*)n + bswap32(n->cg_btotoff));
993 o32 = (u_int32_t*)((u_int8_t*)o + bswap32(n->cg_btotoff));
994 n16 = (u_int16_t*)((u_int8_t*)n + bswap32(n->cg_boff));
995 o16 = (u_int16_t*)((u_int8_t*)o + bswap32(n->cg_boff));
996 }
997 for (i=0; i < btotsize / sizeof(u_int32_t); i++)
998 n32[i] = bswap32(o32[i]);
999
1000 for (i=0; i < fbsize/sizeof(u_int16_t); i++)
1001 n16[i] = bswap16(o16[i]);
1002
1003 if (n->cg_magic == CG_MAGIC) {
1004 n32 = (u_int32_t*)((u_int8_t*)n + n->cg_clustersumoff);
1005 o32 = (u_int32_t*)((u_int8_t*)o + n->cg_clustersumoff);
1006 } else {
1007 n32 = (u_int32_t*)((u_int8_t*)n + bswap32(n->cg_clustersumoff));
1008 o32 = (u_int32_t*)((u_int8_t*)o + bswap32(n->cg_clustersumoff));
1009 }
1010 for (i = 1; i < sblock.fs_contigsumsize + 1; i++)
1011 n32[i] = bswap32(o32[i]);
1012 }
1013
1014 /* Determine how many digits are needed to print a given integer */
1015 static int
1016 count_digits(int num)
1017 {
1018 int ndig;
1019
1020 for(ndig = 1; num > 9; num /=10, ndig++);
1021
1022 return (ndig);
1023 }
1024