1 /* $NetBSD: mkfs.c,v 1.20 2004/06/24 22:30:13 lukem Exp $ */
4 * Copyright (c) 2002 Networks Associates Technology, Inc.
7 * This software was developed for the FreeBSD Project by Marshall
8 * Kirk McKusick and Network Associates Laboratories, the Security
9 * Research Division of Network Associates, Inc. under DARPA/SPAWAR
10 * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
13 * Copyright (c) 1980, 1989, 1993
14 * The Regents of the University of California. All rights reserved.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 #if HAVE_NBTOOL_CONFIG_H
42 #include "nbtool_config.h"
45 #include <sys/cdefs.h>
48 static char sccsid
[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95";
51 __RCSID("$NetBSD: mkfs.c,v 1.20 2004/06/24 22:30:13 lukem Exp $");
56 #include <sys/param.h>
58 #include <sys/resource.h>
69 #include <ufs/ufs/dinode.h>
70 #include <ufs/ufs/ufs_bswap.h>
71 #include <ufs/ffs/fs.h>
73 #include "ffs/ufs_inode.h"
74 #include "ffs/ffs_extern.h"
75 #include "ffs/newfs_extern.h"
77 static void initcg(int, time_t, const fsinfo_t
*);
78 static int ilog2(int);
80 static int count_digits(int);
83 * make file system for cylinder-group style file systems
86 #define POWEROF2(num) (((num) & ((num) - 1)) == 0)
92 #define sblock fsun.fs
97 char pad
[FFS_MAXBSIZE
];
104 char writebuf
[FFS_MAXBSIZE
];
106 static int Oflag
; /* format as an 4.3BSD file system */
107 static int64_t fssize
; /* file system size */
108 static int sectorsize
; /* bytes/sector */
109 static int fsize
; /* fragment size */
110 static int bsize
; /* block size */
111 static int maxbsize
; /* maximum clustering */
112 static int maxblkspercg
;
113 static int minfree
; /* free space threshold */
114 static int opt
; /* optimization preference (space or time) */
115 static int density
; /* number of bytes per inode */
116 static int maxcontig
; /* max contiguous blocks to allocate */
117 static int maxbpg
; /* maximum blocks per file in a cyl group */
118 static int bbsize
; /* boot block size */
119 static int sbsize
; /* superblock size */
120 static int avgfilesize
; /* expected average file size */
121 static int avgfpdir
; /* expected number of files per directory */
124 ffs_mkfs(const char *fsys
, const fsinfo_t
*fsopts
)
126 int fragsperinode
, optimalfpg
, origdensity
, minfpg
, lastminfpg
;
127 int32_t cylno
, i
, csfrags
;
131 int nprintcols
, printcolwidth
;
132 ffs_opt_t
*ffs_opts
= fsopts
->fs_specific
;
134 Oflag
= ffs_opts
->version
;
135 fssize
= fsopts
->size
/ fsopts
->sectorsize
;
136 sectorsize
= fsopts
->sectorsize
;
137 fsize
= ffs_opts
->fsize
;
138 bsize
= ffs_opts
->bsize
;
139 maxbsize
= ffs_opts
->maxbsize
;
140 maxblkspercg
= ffs_opts
->maxblkspercg
;
141 minfree
= ffs_opts
->minfree
;
142 opt
= ffs_opts
->optimization
;
143 density
= ffs_opts
->density
;
144 maxcontig
= ffs_opts
->maxcontig
;
145 maxbpg
= ffs_opts
->maxbpg
;
146 avgfilesize
= ffs_opts
->avgfilesize
;
147 avgfpdir
= ffs_opts
->avgfpdir
;
152 sblock
.fs_old_inodefmt
= FS_42INODEFMT
;
153 sblock
.fs_maxsymlinklen
= 0;
154 sblock
.fs_old_flags
= 0;
156 sblock
.fs_old_inodefmt
= FS_44INODEFMT
;
157 sblock
.fs_maxsymlinklen
= (Oflag
== 1 ? MAXSYMLINKLEN_UFS1
:
159 sblock
.fs_old_flags
= FS_FLAGS_UPDATED
;
163 * Validate the given file system size.
164 * Verify that its last block can actually be accessed.
165 * Convert to file system fragment sized units.
168 printf("preposterous size %lld\n", (long long)fssize
);
171 ffs_wtfs(fssize
- 1, sectorsize
, (char *)&sblock
, fsopts
);
174 * collect and verify the filesystem density info
176 sblock
.fs_avgfilesize
= avgfilesize
;
177 sblock
.fs_avgfpdir
= avgfpdir
;
178 if (sblock
.fs_avgfilesize
<= 0)
179 printf("illegal expected average file size %d\n",
180 sblock
.fs_avgfilesize
), exit(14);
181 if (sblock
.fs_avgfpdir
<= 0)
182 printf("illegal expected number of files per directory %d\n",
183 sblock
.fs_avgfpdir
), exit(15);
185 * collect and verify the block and fragment sizes
187 sblock
.fs_bsize
= bsize
;
188 sblock
.fs_fsize
= fsize
;
189 if (!POWEROF2(sblock
.fs_bsize
)) {
190 printf("block size must be a power of 2, not %d\n",
194 if (!POWEROF2(sblock
.fs_fsize
)) {
195 printf("fragment size must be a power of 2, not %d\n",
199 if (sblock
.fs_fsize
< sectorsize
) {
200 printf("fragment size %d is too small, minimum is %d\n",
201 sblock
.fs_fsize
, sectorsize
);
204 if (sblock
.fs_bsize
< MINBSIZE
) {
205 printf("block size %d is too small, minimum is %d\n",
206 sblock
.fs_bsize
, MINBSIZE
);
209 if (sblock
.fs_bsize
> FFS_MAXBSIZE
) {
210 printf("block size %d is too large, maximum is %d\n",
211 sblock
.fs_bsize
, FFS_MAXBSIZE
);
214 if (sblock
.fs_bsize
< sblock
.fs_fsize
) {
215 printf("block size (%d) cannot be smaller than fragment size (%d)\n",
216 sblock
.fs_bsize
, sblock
.fs_fsize
);
220 if (maxbsize
< bsize
|| !POWEROF2(maxbsize
)) {
221 sblock
.fs_maxbsize
= sblock
.fs_bsize
;
222 printf("Extent size set to %d\n", sblock
.fs_maxbsize
);
223 } else if (sblock
.fs_maxbsize
> FS_MAXCONTIG
* sblock
.fs_bsize
) {
224 sblock
.fs_maxbsize
= FS_MAXCONTIG
* sblock
.fs_bsize
;
225 printf("Extent size reduced to %d\n", sblock
.fs_maxbsize
);
227 sblock
.fs_maxbsize
= maxbsize
;
229 sblock
.fs_maxcontig
= maxcontig
;
230 if (sblock
.fs_maxcontig
< sblock
.fs_maxbsize
/ sblock
.fs_bsize
) {
231 sblock
.fs_maxcontig
= sblock
.fs_maxbsize
/ sblock
.fs_bsize
;
232 printf("Maxcontig raised to %d\n", sblock
.fs_maxbsize
);
235 if (sblock
.fs_maxcontig
> 1)
236 sblock
.fs_contigsumsize
= MIN(sblock
.fs_maxcontig
,FS_MAXCONTIG
);
238 sblock
.fs_bmask
= ~(sblock
.fs_bsize
- 1);
239 sblock
.fs_fmask
= ~(sblock
.fs_fsize
- 1);
240 sblock
.fs_qbmask
= ~sblock
.fs_bmask
;
241 sblock
.fs_qfmask
= ~sblock
.fs_fmask
;
242 for (sblock
.fs_bshift
= 0, i
= sblock
.fs_bsize
; i
> 1; i
>>= 1)
244 for (sblock
.fs_fshift
= 0, i
= sblock
.fs_fsize
; i
> 1; i
>>= 1)
246 sblock
.fs_frag
= numfrags(&sblock
, sblock
.fs_bsize
);
247 for (sblock
.fs_fragshift
= 0, i
= sblock
.fs_frag
; i
> 1; i
>>= 1)
248 sblock
.fs_fragshift
++;
249 if (sblock
.fs_frag
> MAXFRAG
) {
250 printf("fragment size %d is too small, "
251 "minimum with block size %d is %d\n",
252 sblock
.fs_fsize
, sblock
.fs_bsize
,
253 sblock
.fs_bsize
/ MAXFRAG
);
256 sblock
.fs_fsbtodb
= ilog2(sblock
.fs_fsize
/ sectorsize
);
257 sblock
.fs_size
= fssize
= dbtofsb(&sblock
, fssize
);
260 sblock
.fs_magic
= FS_UFS1_MAGIC
;
261 sblock
.fs_sblockloc
= SBLOCK_UFS1
;
262 sblock
.fs_nindir
= sblock
.fs_bsize
/ sizeof(int32_t);
263 sblock
.fs_inopb
= sblock
.fs_bsize
/ sizeof(struct ufs1_dinode
);
264 sblock
.fs_maxsymlinklen
= ((NDADDR
+ NIADDR
) *
266 sblock
.fs_old_inodefmt
= FS_44INODEFMT
;
267 sblock
.fs_old_cgoffset
= 0;
268 sblock
.fs_old_cgmask
= 0xffffffff;
269 sblock
.fs_old_size
= sblock
.fs_size
;
270 sblock
.fs_old_rotdelay
= 0;
271 sblock
.fs_old_rps
= 60;
272 sblock
.fs_old_nspf
= sblock
.fs_fsize
/ sectorsize
;
273 sblock
.fs_old_cpg
= 1;
274 sblock
.fs_old_interleave
= 1;
275 sblock
.fs_old_trackskew
= 0;
276 sblock
.fs_old_cpc
= 0;
277 sblock
.fs_old_postblformat
= 1;
278 sblock
.fs_old_nrpos
= 1;
280 sblock
.fs_magic
= FS_UFS2_MAGIC
;
281 #if 0 /* XXX makefs is used for small filesystems. */
282 sblock
.fs_sblockloc
= SBLOCK_UFS2
;
284 sblock
.fs_sblockloc
= SBLOCK_UFS1
;
286 sblock
.fs_nindir
= sblock
.fs_bsize
/ sizeof(int64_t);
287 sblock
.fs_inopb
= sblock
.fs_bsize
/ sizeof(struct ufs2_dinode
);
288 sblock
.fs_maxsymlinklen
= ((NDADDR
+ NIADDR
) *
293 roundup(howmany(sblock
.fs_sblockloc
+ SBLOCKSIZE
, sblock
.fs_fsize
),
295 sblock
.fs_cblkno
= (daddr_t
)(sblock
.fs_sblkno
+
296 roundup(howmany(SBLOCKSIZE
, sblock
.fs_fsize
), sblock
.fs_frag
));
297 sblock
.fs_iblkno
= sblock
.fs_cblkno
+ sblock
.fs_frag
;
298 sblock
.fs_maxfilesize
= sblock
.fs_bsize
* NDADDR
- 1;
299 for (sizepb
= sblock
.fs_bsize
, i
= 0; i
< NIADDR
; i
++) {
300 sizepb
*= NINDIR(&sblock
);
301 sblock
.fs_maxfilesize
+= sizepb
;
305 * Calculate the number of blocks to put into each cylinder group.
307 * This algorithm selects the number of blocks per cylinder
308 * group. The first goal is to have at least enough data blocks
309 * in each cylinder group to meet the density requirement. Once
310 * this goal is achieved we try to expand to have at least
311 * 1 cylinder group. Once this goal is achieved, we pack as
312 * many blocks into each cylinder group map as will fit.
314 * We start by calculating the smallest number of blocks that we
315 * can put into each cylinder group. If this is too big, we reduce
316 * the density until it fits.
318 origdensity
= density
;
320 fragsperinode
= MAX(numfrags(&sblock
, density
), 1);
321 minfpg
= fragsperinode
* INOPB(&sblock
);
322 if (minfpg
> sblock
.fs_size
)
323 minfpg
= sblock
.fs_size
;
324 sblock
.fs_ipg
= INOPB(&sblock
);
325 sblock
.fs_fpg
= roundup(sblock
.fs_iblkno
+
326 sblock
.fs_ipg
/ INOPF(&sblock
), sblock
.fs_frag
);
327 if (sblock
.fs_fpg
< minfpg
)
328 sblock
.fs_fpg
= minfpg
;
329 sblock
.fs_ipg
= roundup(howmany(sblock
.fs_fpg
, fragsperinode
),
331 sblock
.fs_fpg
= roundup(sblock
.fs_iblkno
+
332 sblock
.fs_ipg
/ INOPF(&sblock
), sblock
.fs_frag
);
333 if (sblock
.fs_fpg
< minfpg
)
334 sblock
.fs_fpg
= minfpg
;
335 sblock
.fs_ipg
= roundup(howmany(sblock
.fs_fpg
, fragsperinode
),
337 if (CGSIZE(&sblock
) < (unsigned long)sblock
.fs_bsize
)
339 density
-= sblock
.fs_fsize
;
341 if (density
!= origdensity
)
342 printf("density reduced from %d to %d\n", origdensity
, density
);
344 if (maxblkspercg
<= 0 || maxblkspercg
>= fssize
)
345 maxblkspercg
= fssize
- 1;
347 * Start packing more blocks into the cylinder group until
348 * it cannot grow any larger, the number of cylinder groups
349 * drops below 1, or we reach the size requested.
351 for ( ; sblock
.fs_fpg
< maxblkspercg
; sblock
.fs_fpg
+= sblock
.fs_frag
) {
352 sblock
.fs_ipg
= roundup(howmany(sblock
.fs_fpg
, fragsperinode
),
354 if (sblock
.fs_size
/ sblock
.fs_fpg
< 1)
356 if (CGSIZE(&sblock
) < (unsigned long)sblock
.fs_bsize
)
358 if (CGSIZE(&sblock
) == (unsigned long)sblock
.fs_bsize
)
360 sblock
.fs_fpg
-= sblock
.fs_frag
;
361 sblock
.fs_ipg
= roundup(howmany(sblock
.fs_fpg
, fragsperinode
),
366 * Check to be sure that the last cylinder group has enough blocks
367 * to be viable. If it is too small, reduce the number of blocks
368 * per cylinder group which will have the effect of moving more
369 * blocks into the last cylinder group.
371 optimalfpg
= sblock
.fs_fpg
;
373 sblock
.fs_ncg
= howmany(sblock
.fs_size
, sblock
.fs_fpg
);
374 lastminfpg
= roundup(sblock
.fs_iblkno
+
375 sblock
.fs_ipg
/ INOPF(&sblock
), sblock
.fs_frag
);
376 if (sblock
.fs_size
< lastminfpg
) {
377 printf("Filesystem size %lld < minimum size of %d\n",
378 (long long)sblock
.fs_size
, lastminfpg
);
381 if (sblock
.fs_size
% sblock
.fs_fpg
>= lastminfpg
||
382 sblock
.fs_size
% sblock
.fs_fpg
== 0)
384 sblock
.fs_fpg
-= sblock
.fs_frag
;
385 sblock
.fs_ipg
= roundup(howmany(sblock
.fs_fpg
, fragsperinode
),
388 if (optimalfpg
!= sblock
.fs_fpg
)
389 printf("Reduced frags per cylinder group from %d to %d %s\n",
390 optimalfpg
, sblock
.fs_fpg
, "to enlarge last cyl group");
391 sblock
.fs_cgsize
= fragroundup(&sblock
, CGSIZE(&sblock
));
392 sblock
.fs_dblkno
= sblock
.fs_iblkno
+ sblock
.fs_ipg
/ INOPF(&sblock
);
394 sblock
.fs_old_spc
= sblock
.fs_fpg
* sblock
.fs_old_nspf
;
395 sblock
.fs_old_nsect
= sblock
.fs_old_spc
;
396 sblock
.fs_old_npsect
= sblock
.fs_old_spc
;
397 sblock
.fs_old_ncyl
= sblock
.fs_ncg
;
401 * fill in remaining fields of the super block
403 sblock
.fs_csaddr
= cgdmin(&sblock
, 0);
405 fragroundup(&sblock
, sblock
.fs_ncg
* sizeof(struct csum
));
408 * Setup memory for temporary in-core cylgroup summaries.
409 * Cribbed from ffs_mountfs().
411 size
= sblock
.fs_cssize
;
412 blks
= howmany(size
, sblock
.fs_fsize
);
413 if (sblock
.fs_contigsumsize
> 0)
414 size
+= sblock
.fs_ncg
* sizeof(int32_t);
415 if ((space
= (char *)calloc(1, size
)) == NULL
)
416 err(1, "memory allocation error for cg summaries");
417 sblock
.fs_csp
= space
;
418 space
= (char *)space
+ sblock
.fs_cssize
;
419 if (sblock
.fs_contigsumsize
> 0) {
422 sblock
.fs_maxcluster
= lp
= space
;
423 for (i
= 0; i
< sblock
.fs_ncg
; i
++)
424 *lp
++ = sblock
.fs_contigsumsize
;
427 sblock
.fs_sbsize
= fragroundup(&sblock
, sizeof(struct fs
));
428 if (sblock
.fs_sbsize
> SBLOCKSIZE
)
429 sblock
.fs_sbsize
= SBLOCKSIZE
;
430 sblock
.fs_minfree
= minfree
;
431 sblock
.fs_maxcontig
= maxcontig
;
432 sblock
.fs_maxbpg
= maxbpg
;
433 sblock
.fs_optim
= opt
;
434 sblock
.fs_cgrotor
= 0;
435 sblock
.fs_pendingblocks
= 0;
436 sblock
.fs_pendinginodes
= 0;
437 sblock
.fs_cstotal
.cs_ndir
= 0;
438 sblock
.fs_cstotal
.cs_nbfree
= 0;
439 sblock
.fs_cstotal
.cs_nifree
= 0;
440 sblock
.fs_cstotal
.cs_nffree
= 0;
444 sblock
.fs_clean
= FS_ISCLEAN
;
446 sblock
.fs_id
[0] = start_time
.tv_sec
;
447 sblock
.fs_id
[1] = random();
448 sblock
.fs_fsmnt
[0] = '\0';
449 csfrags
= howmany(sblock
.fs_cssize
, sblock
.fs_fsize
);
450 sblock
.fs_dsize
= sblock
.fs_size
- sblock
.fs_sblkno
-
451 sblock
.fs_ncg
* (sblock
.fs_dblkno
- sblock
.fs_sblkno
);
452 sblock
.fs_cstotal
.cs_nbfree
=
453 fragstoblks(&sblock
, sblock
.fs_dsize
) -
454 howmany(csfrags
, sblock
.fs_frag
);
455 sblock
.fs_cstotal
.cs_nffree
=
456 fragnum(&sblock
, sblock
.fs_size
) +
457 (fragnum(&sblock
, csfrags
) > 0 ?
458 sblock
.fs_frag
- fragnum(&sblock
, csfrags
) : 0);
459 sblock
.fs_cstotal
.cs_nifree
= sblock
.fs_ncg
* sblock
.fs_ipg
- ROOTINO
;
460 sblock
.fs_cstotal
.cs_ndir
= 0;
461 sblock
.fs_dsize
-= csfrags
;
462 sblock
.fs_time
= start_time
.tv_sec
;
464 sblock
.fs_old_time
= start_time
.tv_sec
;
465 sblock
.fs_old_dsize
= sblock
.fs_dsize
;
466 sblock
.fs_old_csaddr
= sblock
.fs_csaddr
;
467 sblock
.fs_old_cstotal
.cs_ndir
= sblock
.fs_cstotal
.cs_ndir
;
468 sblock
.fs_old_cstotal
.cs_nbfree
= sblock
.fs_cstotal
.cs_nbfree
;
469 sblock
.fs_old_cstotal
.cs_nifree
= sblock
.fs_cstotal
.cs_nifree
;
470 sblock
.fs_old_cstotal
.cs_nffree
= sblock
.fs_cstotal
.cs_nffree
;
473 * Dump out summary information about file system.
475 #define B2MBFACTOR (1 / (1024.0 * 1024.0))
476 printf("%s: %.1fMB (%lld sectors) block size %d, "
477 "fragment size %d\n",
478 fsys
, (float)sblock
.fs_size
* sblock
.fs_fsize
* B2MBFACTOR
,
479 (long long)fsbtodb(&sblock
, sblock
.fs_size
),
480 sblock
.fs_bsize
, sblock
.fs_fsize
);
481 printf("\tusing %d cylinder groups of %.2fMB, %d blks, "
484 (float)sblock
.fs_fpg
* sblock
.fs_fsize
* B2MBFACTOR
,
485 sblock
.fs_fpg
/ sblock
.fs_frag
, sblock
.fs_ipg
);
488 * Now determine how wide each column will be, and calculate how
489 * many columns will fit in a 76 char line. 76 is the width of the
490 * subwindows in sysinst.
492 printcolwidth
= count_digits(
493 fsbtodb(&sblock
, cgsblock(&sblock
, sblock
.fs_ncg
-1)));
494 nprintcols
= 76 / (printcolwidth
+ 2);
497 * allocate space for superblock, cylinder group map, and
498 * two sets of inode blocks.
500 if (sblock
.fs_bsize
< SBLOCKSIZE
)
501 iobufsize
= SBLOCKSIZE
+ 3 * sblock
.fs_bsize
;
503 iobufsize
= 4 * sblock
.fs_bsize
;
504 if ((iobuf
= malloc(iobufsize
)) == 0) {
505 printf("Cannot allocate I/O buffer\n");
508 memset(iobuf
, 0, iobufsize
);
510 * Make a copy of the superblock into the buffer that we will be
511 * writing out in each cylinder group.
513 memcpy(writebuf
, &sblock
, sbsize
);
514 if (fsopts
->needswap
)
515 ffs_sb_swap(&sblock
, (struct fs
*)writebuf
);
516 memcpy(iobuf
, writebuf
, SBLOCKSIZE
);
518 printf("super-block backups (for fsck -b #) at:");
519 for (cylno
= 0; cylno
< sblock
.fs_ncg
; cylno
++) {
520 initcg(cylno
, start_time
.tv_sec
, fsopts
);
521 if (cylno
% nprintcols
== 0)
523 printf(" %*lld,", printcolwidth
,
524 (long long)fsbtodb(&sblock
, cgsblock(&sblock
, cylno
)));
530 * Now construct the initial file system,
531 * then write out the super-block.
533 sblock
.fs_time
= start_time
.tv_sec
;
535 sblock
.fs_old_cstotal
.cs_ndir
= sblock
.fs_cstotal
.cs_ndir
;
536 sblock
.fs_old_cstotal
.cs_nbfree
= sblock
.fs_cstotal
.cs_nbfree
;
537 sblock
.fs_old_cstotal
.cs_nifree
= sblock
.fs_cstotal
.cs_nifree
;
538 sblock
.fs_old_cstotal
.cs_nffree
= sblock
.fs_cstotal
.cs_nffree
;
540 if (fsopts
->needswap
)
541 sblock
.fs_flags
|= FS_SWAPPED
;
542 ffs_write_superblock(&sblock
, fsopts
);
547 * Write out the superblock and its duplicates,
548 * and the cylinder group summaries
551 ffs_write_superblock(struct fs
*fs
, const fsinfo_t
*fsopts
)
553 int cylno
, size
, blks
, i
, saveflag
;
557 saveflag
= fs
->fs_flags
& FS_INTERNAL
;
558 fs
->fs_flags
&= ~FS_INTERNAL
;
560 memcpy(writebuf
, &sblock
, sbsize
);
561 if (fsopts
->needswap
)
562 ffs_sb_swap(fs
, (struct fs
*)writebuf
);
563 ffs_wtfs(fs
->fs_sblockloc
/ sectorsize
, sbsize
, writebuf
, fsopts
);
565 /* Write out the duplicate super blocks */
566 for (cylno
= 0; cylno
< fs
->fs_ncg
; cylno
++)
567 ffs_wtfs(fsbtodb(fs
, cgsblock(fs
, cylno
)),
568 sbsize
, writebuf
, fsopts
);
570 /* Write out the cylinder group summaries */
571 size
= fs
->fs_cssize
;
572 blks
= howmany(size
, fs
->fs_fsize
);
573 space
= (void *)fs
->fs_csp
;
574 if ((wrbuf
= malloc(size
)) == NULL
)
575 err(1, "ffs_write_superblock: malloc %d", size
);
576 for (i
= 0; i
< blks
; i
+= fs
->fs_frag
) {
578 if (i
+ fs
->fs_frag
> blks
)
579 size
= (blks
- i
) * fs
->fs_fsize
;
580 if (fsopts
->needswap
)
581 ffs_csum_swap((struct csum
*)space
,
582 (struct csum
*)wrbuf
, size
);
584 memcpy(wrbuf
, space
, (u_int
)size
);
585 ffs_wtfs(fsbtodb(fs
, fs
->fs_csaddr
+ i
), size
, wrbuf
, fsopts
);
586 space
= (char *)space
+ size
;
589 fs
->fs_flags
|= saveflag
;
593 * Initialize a cylinder group.
596 initcg(int cylno
, time_t utime
, const fsinfo_t
*fsopts
)
599 int32_t i
, j
, d
, dlower
, dupper
, blkno
;
600 struct ufs1_dinode
*dp1
;
601 struct ufs2_dinode
*dp2
;
605 * Determine block bounds for cylinder group.
606 * Allow space for super block summary information in first
609 cbase
= cgbase(&sblock
, cylno
);
610 dmax
= cbase
+ sblock
.fs_fpg
;
611 if (dmax
> sblock
.fs_size
)
612 dmax
= sblock
.fs_size
;
613 dlower
= cgsblock(&sblock
, cylno
) - cbase
;
614 dupper
= cgdmin(&sblock
, cylno
) - cbase
;
616 dupper
+= howmany(sblock
.fs_cssize
, sblock
.fs_fsize
);
617 memset(&acg
, 0, sblock
.fs_cgsize
);
619 acg
.cg_magic
= CG_MAGIC
;
621 acg
.cg_niblk
= sblock
.fs_ipg
;
622 acg
.cg_initediblk
= sblock
.fs_ipg
< 2 * INOPB(&sblock
) ?
623 sblock
.fs_ipg
: 2 * INOPB(&sblock
);
624 acg
.cg_ndblk
= dmax
- cbase
;
625 if (sblock
.fs_contigsumsize
> 0)
626 acg
.cg_nclusterblks
= acg
.cg_ndblk
>> sblock
.fs_fragshift
;
627 start
= &acg
.cg_space
[0] - (u_char
*)(&acg
.cg_firstfield
);
629 acg
.cg_iusedoff
= start
;
631 if (cylno
== sblock
.fs_ncg
- 1)
632 acg
.cg_old_ncyl
= howmany(acg
.cg_ndblk
,
633 sblock
.fs_fpg
/ sblock
.fs_old_cpg
);
635 acg
.cg_old_ncyl
= sblock
.fs_old_cpg
;
636 acg
.cg_old_time
= acg
.cg_time
;
638 acg
.cg_old_niblk
= acg
.cg_niblk
;
640 acg
.cg_initediblk
= 0;
641 acg
.cg_old_btotoff
= start
;
642 acg
.cg_old_boff
= acg
.cg_old_btotoff
+
643 sblock
.fs_old_cpg
* sizeof(int32_t);
644 acg
.cg_iusedoff
= acg
.cg_old_boff
+
645 sblock
.fs_old_cpg
* sizeof(u_int16_t
);
647 acg
.cg_freeoff
= acg
.cg_iusedoff
+ howmany(sblock
.fs_ipg
, CHAR_BIT
);
648 if (sblock
.fs_contigsumsize
<= 0) {
649 acg
.cg_nextfreeoff
= acg
.cg_freeoff
+
650 howmany(sblock
.fs_fpg
, CHAR_BIT
);
652 acg
.cg_clustersumoff
= acg
.cg_freeoff
+
653 howmany(sblock
.fs_fpg
, CHAR_BIT
) - sizeof(int32_t);
654 acg
.cg_clustersumoff
=
655 roundup(acg
.cg_clustersumoff
, sizeof(int32_t));
656 acg
.cg_clusteroff
= acg
.cg_clustersumoff
+
657 (sblock
.fs_contigsumsize
+ 1) * sizeof(int32_t);
658 acg
.cg_nextfreeoff
= acg
.cg_clusteroff
+
659 howmany(fragstoblks(&sblock
, sblock
.fs_fpg
), CHAR_BIT
);
661 if (acg
.cg_nextfreeoff
> sblock
.fs_cgsize
) {
662 printf("Panic: cylinder group too big\n");
665 acg
.cg_cs
.cs_nifree
+= sblock
.fs_ipg
;
667 for (i
= 0; i
< ROOTINO
; i
++) {
668 setbit(cg_inosused(&acg
, 0), i
);
669 acg
.cg_cs
.cs_nifree
--;
673 * In cylno 0, beginning space is reserved
674 * for boot and super blocks.
676 for (d
= 0, blkno
= 0; d
< dlower
;) {
677 ffs_setblock(&sblock
, cg_blksfree(&acg
, 0), blkno
);
678 if (sblock
.fs_contigsumsize
> 0)
679 setbit(cg_clustersfree(&acg
, 0), blkno
);
680 acg
.cg_cs
.cs_nbfree
++;
685 if ((i
= (dupper
& (sblock
.fs_frag
- 1))) != 0) {
686 acg
.cg_frsum
[sblock
.fs_frag
- i
]++;
687 for (d
= dupper
+ sblock
.fs_frag
- i
; dupper
< d
; dupper
++) {
688 setbit(cg_blksfree(&acg
, 0), dupper
);
689 acg
.cg_cs
.cs_nffree
++;
692 for (d
= dupper
, blkno
= dupper
>> sblock
.fs_fragshift
;
693 d
+ sblock
.fs_frag
<= acg
.cg_ndblk
; ) {
694 ffs_setblock(&sblock
, cg_blksfree(&acg
, 0), blkno
);
695 if (sblock
.fs_contigsumsize
> 0)
696 setbit(cg_clustersfree(&acg
, 0), blkno
);
697 acg
.cg_cs
.cs_nbfree
++;
701 if (d
< acg
.cg_ndblk
) {
702 acg
.cg_frsum
[acg
.cg_ndblk
- d
]++;
703 for (; d
< acg
.cg_ndblk
; d
++) {
704 setbit(cg_blksfree(&acg
, 0), d
);
705 acg
.cg_cs
.cs_nffree
++;
708 if (sblock
.fs_contigsumsize
> 0) {
709 int32_t *sump
= cg_clustersum(&acg
, 0);
710 u_char
*mapp
= cg_clustersfree(&acg
, 0);
715 for (i
= 0; i
< acg
.cg_nclusterblks
; i
++) {
716 if ((map
& bit
) != 0) {
718 } else if (run
!= 0) {
719 if (run
> sblock
.fs_contigsumsize
)
720 run
= sblock
.fs_contigsumsize
;
724 if ((i
& (CHAR_BIT
- 1)) != (CHAR_BIT
- 1)) {
732 if (run
> sblock
.fs_contigsumsize
)
733 run
= sblock
.fs_contigsumsize
;
737 sblock
.fs_cs(&sblock
, cylno
) = acg
.cg_cs
;
739 * Write out the duplicate super block, the cylinder group map
740 * and two blocks worth of inodes in a single write.
742 start
= sblock
.fs_bsize
> SBLOCKSIZE
? sblock
.fs_bsize
: SBLOCKSIZE
;
743 memcpy(&iobuf
[start
], &acg
, sblock
.fs_cgsize
);
744 if (fsopts
->needswap
)
745 ffs_cg_swap(&acg
, (struct cg
*)&iobuf
[start
], &sblock
);
746 start
+= sblock
.fs_bsize
;
747 dp1
= (struct ufs1_dinode
*)(&iobuf
[start
]);
748 dp2
= (struct ufs2_dinode
*)(&iobuf
[start
]);
749 for (i
= 0; i
< acg
.cg_initediblk
; i
++) {
750 if (sblock
.fs_magic
== FS_UFS1_MAGIC
) {
751 /* No need to swap, it'll stay random */
752 dp1
->di_gen
= random();
755 dp2
->di_gen
= random();
759 ffs_wtfs(fsbtodb(&sblock
, cgsblock(&sblock
, cylno
)), iobufsize
, iobuf
,
762 * For the old file system, we have to initialize all the inodes.
765 for (i
= 2 * sblock
.fs_frag
;
766 i
< sblock
.fs_ipg
/ INOPF(&sblock
);
767 i
+= sblock
.fs_frag
) {
768 dp1
= (struct ufs1_dinode
*)(&iobuf
[start
]);
769 for (j
= 0; j
< INOPB(&sblock
); j
++) {
770 dp1
->di_gen
= random();
773 ffs_wtfs(fsbtodb(&sblock
, cgimin(&sblock
, cylno
) + i
),
774 sblock
.fs_bsize
, &iobuf
[start
], fsopts
);
780 * read a block from the file system
783 ffs_rdfs(daddr_t bno
, int size
, void *bf
, const fsinfo_t
*fsopts
)
789 offset
*= fsopts
->sectorsize
;
790 if (lseek(fsopts
->fd
, offset
, SEEK_SET
) < 0)
791 err(1, "ffs_rdfs: seek error for sector %lld: %s\n",
792 (long long)bno
, strerror(errno
));
793 n
= read(fsopts
->fd
, bf
, size
);
796 err(1, "ffs_rdfs: read error bno %lld size %d", (long long)bno
,
800 errx(1, "ffs_rdfs: read error for sector %lld: %s\n",
801 (long long)bno
, strerror(errno
));
805 * write a block to the file system
808 ffs_wtfs(daddr_t bno
, int size
, void *bf
, const fsinfo_t
*fsopts
)
814 offset
*= fsopts
->sectorsize
;
815 if (lseek(fsopts
->fd
, offset
, SEEK_SET
) < 0)
816 err(1, "wtfs: seek error for sector %lld: %s\n",
817 (long long)bno
, strerror(errno
));
818 n
= write(fsopts
->fd
, bf
, size
);
820 err(1, "wtfs: write error for sector %lld: %s\n",
821 (long long)bno
, strerror(errno
));
823 errx(1, "wtfs: write error for sector %lld: %s\n",
824 (long long)bno
, strerror(errno
));
828 /* Determine how many digits are needed to print a given integer */
830 count_digits(int num
)
834 for(ndig
= 1; num
> 9; num
/=10, ndig
++);
844 for (n
= 0; n
< sizeof(n
) * CHAR_BIT
; n
++)
847 errx(1, "ilog2: %d is not a power of 2\n", val
);